DJANGO Phase 1
@@ -34,6 +34,7 @@ class Igny8AdminSite(admin.AdminSite):
|
|||||||
'💰 Billing & Accounts': {
|
'💰 Billing & Accounts': {
|
||||||
'models': [
|
'models': [
|
||||||
('igny8_core_auth', 'Plan'),
|
('igny8_core_auth', 'Plan'),
|
||||||
|
('billing', 'PlanLimitUsage'),
|
||||||
('igny8_core_auth', 'Account'),
|
('igny8_core_auth', 'Account'),
|
||||||
('igny8_core_auth', 'Subscription'),
|
('igny8_core_auth', 'Subscription'),
|
||||||
('billing', 'Invoice'),
|
('billing', 'Invoice'),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Billing Module Admin
|
|||||||
"""
|
"""
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.utils.html import format_html
|
from django.utils.html import format_html
|
||||||
|
from django.contrib import messages
|
||||||
from igny8_core.admin.base import AccountAdminMixin
|
from igny8_core.admin.base import AccountAdminMixin
|
||||||
from igny8_core.business.billing.models import (
|
from igny8_core.business.billing.models import (
|
||||||
CreditCostConfig,
|
CreditCostConfig,
|
||||||
@@ -12,12 +13,28 @@ from igny8_core.business.billing.models import (
|
|||||||
PaymentMethodConfig,
|
PaymentMethodConfig,
|
||||||
)
|
)
|
||||||
from .models import CreditTransaction, CreditUsageLog, AccountPaymentMethod
|
from .models import CreditTransaction, CreditUsageLog, AccountPaymentMethod
|
||||||
|
from import_export.admin import ExportMixin
|
||||||
|
from import_export import resources
|
||||||
|
from rangefilter.filters import DateRangeFilter
|
||||||
|
|
||||||
|
|
||||||
|
from rangefilter.filters import DateRangeFilter
|
||||||
|
|
||||||
|
|
||||||
|
class CreditTransactionResource(resources.ModelResource):
|
||||||
|
"""Resource class for exporting Credit Transactions"""
|
||||||
|
class Meta:
|
||||||
|
model = CreditTransaction
|
||||||
|
fields = ('id', 'account__name', 'transaction_type', 'amount', 'balance_after',
|
||||||
|
'description', 'reference_id', 'created_at')
|
||||||
|
export_order = fields
|
||||||
|
|
||||||
|
|
||||||
@admin.register(CreditTransaction)
|
@admin.register(CreditTransaction)
|
||||||
class CreditTransactionAdmin(AccountAdminMixin, admin.ModelAdmin):
|
class CreditTransactionAdmin(ExportMixin, AccountAdminMixin, admin.ModelAdmin):
|
||||||
|
resource_class = CreditTransactionResource
|
||||||
list_display = ['id', 'account', 'transaction_type', 'amount', 'balance_after', 'description', 'created_at']
|
list_display = ['id', 'account', 'transaction_type', 'amount', 'balance_after', 'description', 'created_at']
|
||||||
list_filter = ['transaction_type', 'created_at', 'account']
|
list_filter = ['transaction_type', ('created_at', DateRangeFilter), 'account']
|
||||||
search_fields = ['description', 'account__name']
|
search_fields = ['description', 'account__name']
|
||||||
readonly_fields = ['created_at']
|
readonly_fields = ['created_at']
|
||||||
date_hierarchy = 'created_at'
|
date_hierarchy = 'created_at'
|
||||||
@@ -66,8 +83,18 @@ class InvoiceAdmin(AccountAdminMixin, admin.ModelAdmin):
|
|||||||
readonly_fields = ['created_at', 'updated_at']
|
readonly_fields = ['created_at', 'updated_at']
|
||||||
|
|
||||||
|
|
||||||
|
class PaymentResource(resources.ModelResource):
|
||||||
|
"""Resource class for exporting Payments"""
|
||||||
|
class Meta:
|
||||||
|
model = Payment
|
||||||
|
fields = ('id', 'invoice__invoice_number', 'account__name', 'payment_method',
|
||||||
|
'status', 'amount', 'currency', 'manual_reference', 'approved_by__email',
|
||||||
|
'processed_at', 'created_at')
|
||||||
|
export_order = fields
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Payment)
|
@admin.register(Payment)
|
||||||
class PaymentAdmin(AccountAdminMixin, admin.ModelAdmin):
|
class PaymentAdmin(ExportMixin, AccountAdminMixin, admin.ModelAdmin):
|
||||||
"""
|
"""
|
||||||
Main Payment Admin with approval workflow.
|
Main Payment Admin with approval workflow.
|
||||||
When you change status to 'succeeded', it automatically:
|
When you change status to 'succeeded', it automatically:
|
||||||
@@ -76,6 +103,7 @@ class PaymentAdmin(AccountAdminMixin, admin.ModelAdmin):
|
|||||||
- Activates account
|
- Activates account
|
||||||
- Adds credits
|
- Adds credits
|
||||||
"""
|
"""
|
||||||
|
resource_class = PaymentResource
|
||||||
list_display = [
|
list_display = [
|
||||||
'id',
|
'id',
|
||||||
'invoice',
|
'invoice',
|
||||||
@@ -88,7 +116,7 @@ class PaymentAdmin(AccountAdminMixin, admin.ModelAdmin):
|
|||||||
'approved_by',
|
'approved_by',
|
||||||
'processed_at',
|
'processed_at',
|
||||||
]
|
]
|
||||||
list_filter = ['status', 'payment_method', 'currency', 'created_at', 'processed_at']
|
list_filter = ['status', 'payment_method', 'currency', ('created_at', DateRangeFilter), ('processed_at', DateRangeFilter)]
|
||||||
search_fields = [
|
search_fields = [
|
||||||
'invoice__invoice_number',
|
'invoice__invoice_number',
|
||||||
'account__name',
|
'account__name',
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.contrib import messages
|
||||||
from igny8_core.admin.base import SiteSectorAdminMixin
|
from igny8_core.admin.base import SiteSectorAdminMixin
|
||||||
from .models import Tasks, Images, Content
|
from .models import Tasks, Images, Content
|
||||||
from igny8_core.business.content.models import ContentTaxonomy, ContentAttribute, ContentTaxonomyRelation, ContentClusterMap
|
from igny8_core.business.content.models import ContentTaxonomy, ContentAttribute, ContentTaxonomyRelation, ContentClusterMap
|
||||||
|
from import_export.admin import ExportMixin
|
||||||
|
from import_export import resources
|
||||||
|
|
||||||
|
|
||||||
class ContentTaxonomyInline(admin.TabularInline):
|
class ContentTaxonomyInline(admin.TabularInline):
|
||||||
@@ -13,13 +16,24 @@ class ContentTaxonomyInline(admin.TabularInline):
|
|||||||
verbose_name_plural = 'Taxonomy Terms (Tags & Categories)'
|
verbose_name_plural = 'Taxonomy Terms (Tags & Categories)'
|
||||||
|
|
||||||
|
|
||||||
|
class TaskResource(resources.ModelResource):
|
||||||
|
"""Resource class for exporting Tasks"""
|
||||||
|
class Meta:
|
||||||
|
model = Tasks
|
||||||
|
fields = ('id', 'title', 'description', 'status', 'content_type', 'content_structure',
|
||||||
|
'site__name', 'sector__name', 'cluster__name', 'created_at', 'updated_at')
|
||||||
|
export_order = fields
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Tasks)
|
@admin.register(Tasks)
|
||||||
class TasksAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
|
class TasksAdmin(ExportMixin, SiteSectorAdminMixin, admin.ModelAdmin):
|
||||||
|
resource_class = TaskResource
|
||||||
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'status', 'cluster', 'created_at']
|
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'status', 'cluster', 'created_at']
|
||||||
list_filter = ['status', 'content_type', 'content_structure', 'site', 'sector', 'cluster']
|
list_filter = ['status', 'content_type', 'content_structure', 'site', 'sector', 'cluster']
|
||||||
search_fields = ['title', 'description']
|
search_fields = ['title', 'description']
|
||||||
ordering = ['-created_at']
|
ordering = ['-created_at']
|
||||||
readonly_fields = ['created_at', 'updated_at']
|
readonly_fields = ['created_at', 'updated_at']
|
||||||
|
actions = ['bulk_set_status_draft', 'bulk_set_status_in_progress', 'bulk_set_status_completed']
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
('Basic Info', {
|
('Basic Info', {
|
||||||
@@ -37,6 +51,24 @@ class TasksAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def bulk_set_status_draft(self, request, queryset):
|
||||||
|
"""Set selected tasks to draft status"""
|
||||||
|
updated = queryset.update(status='draft')
|
||||||
|
self.message_user(request, f'{updated} task(s) set to draft.', messages.SUCCESS)
|
||||||
|
bulk_set_status_draft.short_description = 'Set status to Draft'
|
||||||
|
|
||||||
|
def bulk_set_status_in_progress(self, request, queryset):
|
||||||
|
"""Set selected tasks to in-progress status"""
|
||||||
|
updated = queryset.update(status='in_progress')
|
||||||
|
self.message_user(request, f'{updated} task(s) set to in progress.', messages.SUCCESS)
|
||||||
|
bulk_set_status_in_progress.short_description = 'Set status to In Progress'
|
||||||
|
|
||||||
|
def bulk_set_status_completed(self, request, queryset):
|
||||||
|
"""Set selected tasks to completed status"""
|
||||||
|
updated = queryset.update(status='completed')
|
||||||
|
self.message_user(request, f'{updated} task(s) set to completed.', messages.SUCCESS)
|
||||||
|
bulk_set_status_completed.short_description = 'Set status to Completed'
|
||||||
|
|
||||||
def get_site_display(self, obj):
|
def get_site_display(self, obj):
|
||||||
"""Safely get site name"""
|
"""Safely get site name"""
|
||||||
try:
|
try:
|
||||||
@@ -93,14 +125,26 @@ class ImagesAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
|
|||||||
return '-'
|
return '-'
|
||||||
|
|
||||||
|
|
||||||
|
class ContentResource(resources.ModelResource):
|
||||||
|
"""Resource class for exporting Content"""
|
||||||
|
class Meta:
|
||||||
|
model = Content
|
||||||
|
fields = ('id', 'title', 'content_type', 'content_structure', 'status', 'source',
|
||||||
|
'site__name', 'sector__name', 'cluster__name', 'word_count',
|
||||||
|
'meta_title', 'meta_description', 'primary_keyword', 'external_url', 'created_at')
|
||||||
|
export_order = fields
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Content)
|
@admin.register(Content)
|
||||||
class ContentAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
|
class ContentAdmin(ExportMixin, SiteSectorAdminMixin, admin.ModelAdmin):
|
||||||
|
resource_class = ContentResource
|
||||||
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'source', 'status', 'get_taxonomy_count', 'created_at']
|
list_display = ['title', 'content_type', 'content_structure', 'site', 'sector', 'source', 'status', 'get_taxonomy_count', 'created_at']
|
||||||
list_filter = ['content_type', 'content_structure', 'source', 'status', 'site', 'sector', 'created_at']
|
list_filter = ['content_type', 'content_structure', 'source', 'status', 'site', 'sector', 'created_at']
|
||||||
search_fields = ['title', 'content_html', 'external_url']
|
search_fields = ['title', 'content_html', 'external_url']
|
||||||
ordering = ['-created_at']
|
ordering = ['-created_at']
|
||||||
readonly_fields = ['created_at', 'updated_at', 'word_count', 'get_tags_display', 'get_categories_display']
|
readonly_fields = ['created_at', 'updated_at', 'word_count', 'get_tags_display', 'get_categories_display']
|
||||||
inlines = [ContentTaxonomyInline]
|
inlines = [ContentTaxonomyInline]
|
||||||
|
actions = ['bulk_set_status_published', 'bulk_set_status_draft']
|
||||||
|
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
('Basic Info', {
|
('Basic Info', {
|
||||||
@@ -152,6 +196,18 @@ class ContentAdmin(SiteSectorAdminMixin, admin.ModelAdmin):
|
|||||||
return 'No categories'
|
return 'No categories'
|
||||||
get_categories_display.short_description = 'Categories'
|
get_categories_display.short_description = 'Categories'
|
||||||
|
|
||||||
|
def bulk_set_status_published(self, request, queryset):
|
||||||
|
"""Set selected content to published status"""
|
||||||
|
updated = queryset.update(status='published')
|
||||||
|
self.message_user(request, f'{updated} content item(s) set to published.', messages.SUCCESS)
|
||||||
|
bulk_set_status_published.short_description = 'Set status to Published'
|
||||||
|
|
||||||
|
def bulk_set_status_draft(self, request, queryset):
|
||||||
|
"""Set selected content to draft status"""
|
||||||
|
updated = queryset.update(status='draft')
|
||||||
|
self.message_user(request, f'{updated} content item(s) set to draft.', messages.SUCCESS)
|
||||||
|
bulk_set_status_draft.short_description = 'Set status to Draft'
|
||||||
|
|
||||||
def get_site_display(self, obj):
|
def get_site_display(self, obj):
|
||||||
"""Safely get site name"""
|
"""Safely get site name"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -36,16 +36,25 @@ ALLOWED_HOSTS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
# Django Admin Enhancements (must be before django.contrib.admin)
|
||||||
|
'admin_interface',
|
||||||
|
'colorfield',
|
||||||
|
# Core Django apps
|
||||||
'igny8_core.admin.apps.Igny8AdminConfig', # Custom admin config
|
'igny8_core.admin.apps.Igny8AdminConfig', # Custom admin config
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
# Third-party apps
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'django_filters',
|
'django_filters',
|
||||||
'corsheaders',
|
'corsheaders',
|
||||||
'drf_spectacular', # OpenAPI 3.0 schema generation
|
'drf_spectacular', # OpenAPI 3.0 schema generation
|
||||||
|
'import_export',
|
||||||
|
'rangefilter',
|
||||||
|
'django_celery_results',
|
||||||
|
# IGNY8 apps
|
||||||
'igny8_core.auth.apps.Igny8CoreAuthConfig', # Use app config with custom label
|
'igny8_core.auth.apps.Igny8CoreAuthConfig', # Use app config with custom label
|
||||||
'igny8_core.ai.apps.AIConfig', # AI Framework
|
'igny8_core.ai.apps.AIConfig', # AI Framework
|
||||||
'igny8_core.modules.planner.apps.PlannerConfig',
|
'igny8_core.modules.planner.apps.PlannerConfig',
|
||||||
@@ -591,6 +600,16 @@ LOGGING = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Admin Interface Configuration
|
||||||
|
X_FRAME_OPTIONS = 'SAMEORIGIN' # Required for django-admin-interface
|
||||||
|
|
||||||
|
# Celery Results Backend
|
||||||
|
CELERY_RESULT_BACKEND = 'django-db'
|
||||||
|
CELERY_CACHE_BACKEND = 'django-cache'
|
||||||
|
|
||||||
|
# Import/Export Settings
|
||||||
|
IMPORT_EXPORT_USE_TRANSACTIONS = True
|
||||||
|
|
||||||
# Billing / Payments configuration
|
# Billing / Payments configuration
|
||||||
STRIPE_PUBLIC_KEY = os.getenv('STRIPE_PUBLIC_KEY', '')
|
STRIPE_PUBLIC_KEY = os.getenv('STRIPE_PUBLIC_KEY', '')
|
||||||
STRIPE_SECRET_KEY = os.getenv('STRIPE_SECRET_KEY', '')
|
STRIPE_SECRET_KEY = os.getenv('STRIPE_SECRET_KEY', '')
|
||||||
|
|||||||
@@ -15,3 +15,9 @@ psutil>=5.9.0
|
|||||||
docker>=7.0.0
|
docker>=7.0.0
|
||||||
drf-spectacular>=0.27.0
|
drf-spectacular>=0.27.0
|
||||||
stripe>=7.10.0
|
stripe>=7.10.0
|
||||||
|
|
||||||
|
# Django Admin Enhancements
|
||||||
|
django-admin-interface==0.26.0
|
||||||
|
django-import-export==3.3.1
|
||||||
|
django-admin-rangefilter==0.11.1
|
||||||
|
django-celery-results==2.5.1
|
||||||
|
|||||||
@@ -1,29 +1,20 @@
|
|||||||
'use strict';
|
/** global: django */
|
||||||
{
|
|
||||||
// Call function fn when the DOM is loaded and ready. If it is already
|
|
||||||
// loaded, call the function now.
|
|
||||||
// http://youmightnotneedjquery.com/#ready
|
|
||||||
function ready(fn) {
|
|
||||||
if (document.readyState !== 'loading') {
|
|
||||||
fn();
|
|
||||||
} else {
|
|
||||||
document.addEventListener('DOMContentLoaded', fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ready(function() {
|
if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined') {
|
||||||
function handleClick(event) {
|
(function($) {
|
||||||
event.preventDefault();
|
'use strict';
|
||||||
const params = new URLSearchParams(window.location.search);
|
$(document).ready(function() {
|
||||||
if (params.has('_popup')) {
|
$('.cancel-link').click(function(e) {
|
||||||
window.close(); // Close the popup.
|
e.preventDefault();
|
||||||
} else {
|
var parentWindow = window.parent;
|
||||||
window.history.back(); // Otherwise, go back.
|
if (parentWindow && typeof(parentWindow.dismissRelatedObjectModal) === 'function' && parentWindow !== window) {
|
||||||
}
|
parentWindow.dismissRelatedObjectModal();
|
||||||
}
|
} else {
|
||||||
|
// fallback to default behavior
|
||||||
document.querySelectorAll('.cancel-link').forEach(function(el) {
|
window.history.back();
|
||||||
el.addEventListener('click', handleClick);
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
})(django.jQuery);
|
||||||
}
|
}
|
||||||
|
|||||||
49
backend/staticfiles/admin/js/collapse.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/*global gettext*/
|
||||||
|
/* copied from django 4.0.7 */
|
||||||
|
'use strict';
|
||||||
|
{
|
||||||
|
window.addEventListener('load', function() {
|
||||||
|
// Add anchor tag for Show/Hide link
|
||||||
|
const fieldsets = document.querySelectorAll('fieldset.collapse');
|
||||||
|
for (const [i, elem] of fieldsets.entries()) {
|
||||||
|
// Don't hide if fields in this fieldset have errors
|
||||||
|
if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) {
|
||||||
|
const h2 = elem.querySelector('h2');
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.id = 'fieldsetcollapser' + i;
|
||||||
|
link.className = 'collapse-toggle';
|
||||||
|
link.href = '#';
|
||||||
|
// changed: can opt into starting visible
|
||||||
|
if (elem.classList.contains('expanded')) {
|
||||||
|
link.textContent = gettext('Hide');
|
||||||
|
} else {
|
||||||
|
link.textContent = gettext('Show');
|
||||||
|
elem.classList.add('collapsed');
|
||||||
|
}
|
||||||
|
h2.appendChild(document.createTextNode(' ('));
|
||||||
|
h2.appendChild(link);
|
||||||
|
h2.appendChild(document.createTextNode(')'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add toggle to hide/show anchor tag
|
||||||
|
const toggleFunc = function(ev) {
|
||||||
|
if (ev.target.matches('.collapse-toggle')) {
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.stopPropagation();
|
||||||
|
const fieldset = ev.target.closest('fieldset');
|
||||||
|
if (fieldset.classList.contains('collapsed')) {
|
||||||
|
// Show
|
||||||
|
ev.target.textContent = gettext('Hide');
|
||||||
|
fieldset.classList.remove('collapsed');
|
||||||
|
} else {
|
||||||
|
// Hide
|
||||||
|
ev.target.textContent = gettext('Show');
|
||||||
|
fieldset.classList.add('collapsed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.querySelectorAll('fieldset.module').forEach(function(el) {
|
||||||
|
el.addEventListener('click', toggleFunc);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,15 +1,48 @@
|
|||||||
'use strict';
|
(function() {
|
||||||
{
|
|
||||||
const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
|
'use strict';
|
||||||
switch(initData.action) {
|
|
||||||
case 'change':
|
var windowRef = window;
|
||||||
opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value);
|
var windowRefProxy;
|
||||||
break;
|
var windowName, widgetName;
|
||||||
case 'delete':
|
var openerRef = windowRef.opener;
|
||||||
opener.dismissDeleteRelatedObjectPopup(window, initData.value);
|
if (!openerRef) {
|
||||||
break;
|
// related modal is active
|
||||||
default:
|
openerRef = windowRef.parent;
|
||||||
opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj);
|
windowName = windowRef.name;
|
||||||
break;
|
widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
|
||||||
|
if (typeof(openerRef.id_to_windowname) === 'function') {
|
||||||
|
// django < 3.1 compatibility
|
||||||
|
widgetName = openerRef.id_to_windowname(widgetName);
|
||||||
|
}
|
||||||
|
windowRefProxy = {
|
||||||
|
name: widgetName,
|
||||||
|
location: windowRef.location,
|
||||||
|
close: function() {
|
||||||
|
openerRef.dismissRelatedObjectModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
windowRef = windowRefProxy;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// default django popup_response.js
|
||||||
|
var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
|
||||||
|
switch (initData.action) {
|
||||||
|
case 'change':
|
||||||
|
if (typeof(openerRef.dismissChangeRelatedObjectPopup) === 'function') {
|
||||||
|
openerRef.dismissChangeRelatedObjectPopup(windowRef, initData.value, initData.obj, initData.new_value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
if (typeof(openerRef.dismissDeleteRelatedObjectPopup) === 'function') {
|
||||||
|
openerRef.dismissDeleteRelatedObjectPopup(windowRef, initData.value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (typeof(openerRef.dismissAddRelatedObjectPopup) === 'function') {
|
||||||
|
openerRef.dismissAddRelatedObjectPopup(windowRef, initData.value, initData.obj);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/** global: django */
|
||||||
|
|
||||||
|
if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined')
|
||||||
|
{
|
||||||
|
(function($) {
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
function collapsibleInline(scope, collapsed) {
|
||||||
|
var fieldsetCollapsed = collapsed;
|
||||||
|
var fieldsetEl = $(scope).find('> fieldset.module');
|
||||||
|
fieldsetEl.addClass('collapse');
|
||||||
|
var fieldsetHasErrors = (fieldsetEl.children('.errors').length > 0);
|
||||||
|
if (fieldsetHasErrors === true) {
|
||||||
|
fieldsetCollapsed = false;
|
||||||
|
}
|
||||||
|
if (fieldsetCollapsed === true) {
|
||||||
|
fieldsetEl.addClass('collapsed');
|
||||||
|
}
|
||||||
|
var collapseToggleText = (fieldsetCollapsed ? gettext('Show') : gettext('Hide'));
|
||||||
|
var collapseToggleHTML = ' (<a class="collapse-toggle" href="#">' + collapseToggleText + '</a>)';
|
||||||
|
var headerEl = fieldsetEl.find('> h2,> h3');
|
||||||
|
headerEl.append(collapseToggleHTML);
|
||||||
|
}
|
||||||
|
|
||||||
|
var stackedInlinesOptionSel = '.admin-interface.collapsible-stacked-inlines';
|
||||||
|
var stackedInlinesSel = stackedInlinesOptionSel + ' .inline-group[data-inline-type="stacked"]';
|
||||||
|
var stackedInlinesCollapsed = $(stackedInlinesOptionSel).hasClass('collapsible-stacked-inlines-collapsed');
|
||||||
|
|
||||||
|
var tabularInlinesOptionSel = '.admin-interface.collapsible-tabular-inlines';
|
||||||
|
var tabularInlinesSel = tabularInlinesOptionSel + ' .inline-group[data-inline-type="tabular"] .inline-related.tabular';
|
||||||
|
var tabularInlinesCollapsed = $(stackedInlinesOptionSel).hasClass('collapsible-tabular-inlines-collapsed');
|
||||||
|
|
||||||
|
$(stackedInlinesSel).each(function() {
|
||||||
|
collapsibleInline(this, stackedInlinesCollapsed);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(tabularInlinesSel).each(function() {
|
||||||
|
collapsibleInline(this, tabularInlinesCollapsed);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})(django.jQuery);
|
||||||
|
}
|
||||||
610
backend/staticfiles/admin_interface/css/admin-interface-fix.css
Normal file
@@ -0,0 +1,610 @@
|
|||||||
|
.admin-interface {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix login */
|
||||||
|
.admin-interface.login #container {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 360px;
|
||||||
|
margin: 15px auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #content {
|
||||||
|
padding: 15px 30px 30px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:768px){
|
||||||
|
.admin-interface.login #container {
|
||||||
|
margin: 90px auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #header {
|
||||||
|
min-height: auto;
|
||||||
|
padding: 10px 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #header #branding h1 {
|
||||||
|
margin-right:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #header #branding h1 img.logo {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #header #branding h1 img.logo+span {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #login-form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login .submit-row {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-top: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login .submit-row label {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login .submit-row input[type="submit"] {
|
||||||
|
width: 100%;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.login #footer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
/* end login fix*/
|
||||||
|
|
||||||
|
.admin-interface #header {
|
||||||
|
height: auto;
|
||||||
|
min-height: 55px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:1024px) {
|
||||||
|
.admin-interface #header {
|
||||||
|
align-items: start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1 img.logo {
|
||||||
|
margin-top:10px;
|
||||||
|
margin-bottom:10px;
|
||||||
|
margin-right:15px;
|
||||||
|
display:inline-block !important; /* override inline display:none; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1 span {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1 img.logo+span {
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #user-tools {
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #user-tools br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.admin-interface #user-tools br {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface fieldset.collapse {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface fieldset.collapse.collapsed a.collapse-toggle,
|
||||||
|
.admin-interface fieldset.collapse a.collapse-toggle,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module a.collapse-toggle,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module.collapsed a.collapse-toggle {
|
||||||
|
font-weight: normal;
|
||||||
|
text-transform: lowercase;
|
||||||
|
font-size: 12px;
|
||||||
|
text-decoration: underline;
|
||||||
|
padding: 0 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.admin-interface #changelist .actions .button,
|
||||||
|
.admin-interface #changelist .actions .action-counter {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist .paginator {
|
||||||
|
margin-top:-1px; /* merge 2 borders into 1 */
|
||||||
|
line-height:42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a,
|
||||||
|
.admin-interface .paginator a:link,
|
||||||
|
.admin-interface .paginator a:visited,
|
||||||
|
.admin-interface .paginator .this-page {
|
||||||
|
padding:7px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a,
|
||||||
|
.admin-interface .paginator .this-page {
|
||||||
|
margin-left:0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator .this-page,
|
||||||
|
.admin-interface .paginator a.end {
|
||||||
|
margin-right:25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator .this-page + a:not(.showall) {
|
||||||
|
margin-left:-25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.admin-interface .paginator a.showall,
|
||||||
|
body.admin-interface .paginator a.showall:link,
|
||||||
|
body.admin-interface .paginator a.showall:visited {
|
||||||
|
margin-left:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix help text icon on newline */
|
||||||
|
.admin-interface .inline-group thead th {
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group thead th img {
|
||||||
|
vertical-align: -2px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .inlinechangelink {
|
||||||
|
background-size: contain;
|
||||||
|
padding-left: 15px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .file-thumbnail > a {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned p.file-upload {
|
||||||
|
display:table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload > a {
|
||||||
|
margin-right:20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload .clearable-file-input {
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload .clearable-file-input label {
|
||||||
|
padding-bottom:0px;
|
||||||
|
margin-left:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload > input[type="file"] {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:767px){
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload > a {
|
||||||
|
margin-right:0px;
|
||||||
|
display: block;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload .clearable-file-input {
|
||||||
|
display: block;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-bottom: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .form-row p.file-upload > input[type="file"] {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix inline horizontal scroll caused by checkbox-row */
|
||||||
|
.admin-interface form .form-row > div.checkbox-row {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* FIX WIDE FIELDSET HELPS / ERROR MESSAGES */
|
||||||
|
.admin-interface form .wide p.help,
|
||||||
|
.admin-interface form .wide div.help {
|
||||||
|
padding-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .wide input + p.help,
|
||||||
|
.admin-interface form .wide input + div.help {
|
||||||
|
margin-left: 160px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:767px){
|
||||||
|
.admin-interface form .form-row div.help {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface form .wide ul.errorlist {
|
||||||
|
margin-left: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LIST FILTER */
|
||||||
|
.admin-interface .module.filtered h2 {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter {
|
||||||
|
min-width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.admin-interface .module.filtered #changelist-filter {
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter h2 {
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter h2 + h3 {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter h3 {
|
||||||
|
margin-top: 12px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist-form .results {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* begin fix issue #13 - Datetime widget broken in long inlines */
|
||||||
|
.admin-interface p.datetime {
|
||||||
|
white-space:nowrap;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
/* begin fix lateral padding to align text with field labels */
|
||||||
|
.admin-interface .module h2,
|
||||||
|
.admin-interface.dashboard .module caption,
|
||||||
|
.admin-interface.dashboard .module th,
|
||||||
|
.admin-interface .module.filtered h2,
|
||||||
|
.admin-interface .inline-group h2,
|
||||||
|
.admin-interface #nav-sidebar .module caption,
|
||||||
|
.admin-interface #nav-sidebar .module th {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
/* begin fix restrict tabular-inline horizontal-scroll to inline-group instead of whole page */
|
||||||
|
.admin-interface .inline-group[data-inline-type="tabular"] {
|
||||||
|
overflow-x:auto;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
/* begin fix stacked-inline margin-bottom in responsive small viewport */
|
||||||
|
.admin-interface .inline-group[data-inline-type="stacked"] .module {
|
||||||
|
margin-bottom:0px;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
/* begin fix tabular inlines horizontal scroll */
|
||||||
|
.admin-interface .inline-related.tabular {
|
||||||
|
overflow-x: scroll;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
.admin-interface .inline-related.tabular fieldset.module {
|
||||||
|
display: contents;
|
||||||
|
width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.admin-interface .inline-related.tabular fieldset.module h2 {
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
.admin-interface .inline-related.tabular fieldset.module table {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
}
|
||||||
|
.admin-interface .inline-related.tabular fieldset.module table tbody tr {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
.admin-interface .inline-related h3 {
|
||||||
|
padding:6px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* begin fix issue #12 - Inlines bad delete buttons alignement */
|
||||||
|
.admin-interface .inline-group .tabular thead th:last-child:not([class]):not([style]) {
|
||||||
|
text-align:right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular tr td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular tr td.delete {
|
||||||
|
text-align:right;
|
||||||
|
padding-right:15px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular tr td input[type="checkbox"] {
|
||||||
|
margin: 7px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular tr td.delete a.inline-deletelink {
|
||||||
|
margin-top:4px;
|
||||||
|
overflow:hidden;
|
||||||
|
text-indent:9999px;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
/* top-right buttons color on hover -> just a lighten grey */
|
||||||
|
.admin-interface .object-tools a {
|
||||||
|
color:#FFFFFF;
|
||||||
|
}
|
||||||
|
.admin-interface .object-tools a:focus,
|
||||||
|
.admin-interface .object-tools a:hover,
|
||||||
|
.admin-interface .object-tools li:focus a,
|
||||||
|
.admin-interface .object-tools li:hover a {
|
||||||
|
background-color:#AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* improve responsive selector */
|
||||||
|
|
||||||
|
/* fix [stacked, not-stacked] equalize horizontal and vertical select padding for selector */
|
||||||
|
.admin-interface .selector .selector-available select,
|
||||||
|
.admin-interface .selector .selector-chosen select {
|
||||||
|
padding: 7px 10px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix [stacked, not-stacked] select options text overflow */
|
||||||
|
.admin-interface .selector .selector-available select option,
|
||||||
|
.admin-interface .selector .selector-chosen select option {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix [not-stacked] equalize selectors height by adding the height of the .selector-available filter-bar */
|
||||||
|
.admin-interface .selector:not(.stacked) .selector-chosen select {
|
||||||
|
height: calc(46px + 17.2em) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix nav-sidebar (added in django 3.1.0) */
|
||||||
|
.admin-interface #toggle-nav-sidebar {
|
||||||
|
top: 10px;
|
||||||
|
left: 0;
|
||||||
|
z-index: 20;
|
||||||
|
flex: 0 0 30px;
|
||||||
|
width: 30px;
|
||||||
|
height: 45px;
|
||||||
|
margin-top: 10px;
|
||||||
|
margin-right: -30px;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #eaeaea;
|
||||||
|
border-left: none;
|
||||||
|
outline: none;
|
||||||
|
-webkit-box-shadow: 4px 4px 8px -4px #DBDBDB;
|
||||||
|
-moz-box-shadow: 4px 4px 8px -4px #DBDBDB;
|
||||||
|
box-shadow: 4px 4px 8px -4px #DBDBDB;
|
||||||
|
/*transition: left .3s;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .toggle-nav-sidebar::before {
|
||||||
|
margin-top: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .main > #nav-sidebar + .content,
|
||||||
|
.admin-interface .main.shifted > #nav-sidebar + .content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hide nav-sidebar below 1280px to prevent horizontal overflow issues */
|
||||||
|
@media (max-width:1279px) {
|
||||||
|
.admin-interface #nav-sidebar,
|
||||||
|
.admin-interface #toggle-nav-sidebar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #nav-sidebar {
|
||||||
|
flex: 0 0 360px;
|
||||||
|
left: -360px;
|
||||||
|
margin-left: -360px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
padding: 40px 40px 40px 40px;
|
||||||
|
border-top: none;
|
||||||
|
border-bottom: none;
|
||||||
|
border-left: none;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
/*transition: left .3s, margin-left .3s;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #nav-filter {
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
height: 30px;
|
||||||
|
margin: 0 0 30px 0;
|
||||||
|
padding: 5px 6px;
|
||||||
|
outline-width: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1280px) {
|
||||||
|
.admin-interface #main.shifted > #toggle-nav-sidebar {
|
||||||
|
left: 359px;
|
||||||
|
}
|
||||||
|
.admin-interface #main.shifted > #nav-sidebar {
|
||||||
|
left: 0px;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.admin-interface #main:not(.shifted) > .content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.admin-interface.change-list:not(.popup) #main.shifted > #nav-sidebar + .content,
|
||||||
|
.admin-interface.change-form:not(.popup) #main.shifted > #nav-sidebar + .content {
|
||||||
|
max-width: calc(100% - 360px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fixed related widget and select2 */
|
||||||
|
/* begin fix issue #10 - Related widget broken in long tabular inline */
|
||||||
|
.admin-interface .related-widget-wrapper {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
.admin-interface .related-widget-wrapper select + .related-widget-wrapper-link,
|
||||||
|
.admin-interface .related-widget-wrapper .select2-container + .related-widget-wrapper-link {
|
||||||
|
margin-left: 12px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.admin-interface.change-form select {
|
||||||
|
min-width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.admin-interface.change-form select {
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.change-form .inline-related.tabular select {
|
||||||
|
min-width: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fixed time widget header border radius */
|
||||||
|
.admin-interface .clockbox.module h2 {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix searchbar overriden padding */
|
||||||
|
.admin-interface #changelist #changelist-search #searchbar {
|
||||||
|
padding: 2px 5px 3px 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.admin-interface #changelist #changelist-search #searchbar,
|
||||||
|
.admin-interface #changelist #changelist-search input[type="submit"],
|
||||||
|
.admin-interface #changelist #changelist-search .quiet {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
.admin-interface #changelist #changelist-search label img {
|
||||||
|
vertical-align: text-top;
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.admin-interface #changelist #toolbar {
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
/* fixed changelist search size when there are search results and .quiet is visible */
|
||||||
|
.admin-interface #changelist-search label img {
|
||||||
|
margin-top: 2px;
|
||||||
|
}
|
||||||
|
.admin-interface #changelist-search .quiet {
|
||||||
|
margin: 0 0 0 10px;
|
||||||
|
align-self: center;
|
||||||
|
flex-basis: content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
/* fixed responsive widgets */
|
||||||
|
.admin-interface .aligned.collapsed .form-row {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row > div {
|
||||||
|
display: flex;
|
||||||
|
max-width: 100vw;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row .help {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row .checkbox-row label {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row input[type="file"],
|
||||||
|
.admin-interface .aligned .form-row input[type="text"],
|
||||||
|
.admin-interface .aligned .form-row input[type="email"] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fix textarea horizontal scroll on Firefox */
|
||||||
|
.admin-interface .aligned .form-row textarea {
|
||||||
|
width: 100% !important;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row .datetime input[type="text"] {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row span + .file-upload {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row .file-upload input[type="file"] {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
497
backend/staticfiles/admin_interface/css/admin-interface.css
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root .admin-interface {
|
||||||
|
--primary: #79aec8;
|
||||||
|
--secondary: #417690;
|
||||||
|
--accent: #f5dd5d;
|
||||||
|
--primary-fg: #fff;
|
||||||
|
--body-fg: #333;
|
||||||
|
--body-bg: #fff;
|
||||||
|
--body-quiet-color: #666;
|
||||||
|
--body-loud-color: #000;
|
||||||
|
--header-color: #ffc;
|
||||||
|
--header-branding-color: var(--accent);
|
||||||
|
--header-bg: var(--secondary);
|
||||||
|
--header-link-color: var(--primary-fg);
|
||||||
|
--breadcrumbs-fg: #c4dce8;
|
||||||
|
--breadcrumbs-link-fg: var(--body-bg);
|
||||||
|
--breadcrumbs-bg: var(--primary);
|
||||||
|
--link-fg: #447e9b;
|
||||||
|
--link-hover-color: #036;
|
||||||
|
--link-selected-fg: #5b80b2;
|
||||||
|
--hairline-color: #e8e8e8;
|
||||||
|
--border-color: #ccc;
|
||||||
|
--error-fg: #ba2121;
|
||||||
|
--message-success-bg: #dfd;
|
||||||
|
--message-warning-bg: #ffc;
|
||||||
|
--message-error-bg: #ffefef;
|
||||||
|
--darkened-bg: #f8f8f8;
|
||||||
|
--selected-bg: #e4e4e4;
|
||||||
|
--selected-row: #ffc;
|
||||||
|
--button-fg: #fff;
|
||||||
|
--button-bg: var(--primary);
|
||||||
|
--button-hover-bg: #609ab6;
|
||||||
|
--default-button-bg: var(--secondary);
|
||||||
|
--default-button-hover-bg: #205067;
|
||||||
|
--close-button-bg: #888;
|
||||||
|
--close-button-hover-bg: #747474;
|
||||||
|
--delete-button-bg: #ba2121;
|
||||||
|
--delete-button-hover-bg: #a41515;
|
||||||
|
--object-tools-fg: var(--button-fg);
|
||||||
|
--object-tools-bg: var(--close-button-bg);
|
||||||
|
--object-tools-hover-bg: var(--close-button-hover-bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #header {
|
||||||
|
background: var(--admin-interface-header-background-color);
|
||||||
|
color: var(--admin-interface-header-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #header + #main {
|
||||||
|
border-top: var(--admin-interface-main-border-top);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .environment-label {
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .environment-label::before {
|
||||||
|
content: "";
|
||||||
|
display: inline-block;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: var(--admin-interface-env-color);
|
||||||
|
border-radius: 100%;
|
||||||
|
margin-right: 6px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .environment-label::after {
|
||||||
|
content: " - ";
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.admin-interface .environment-label::after {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 15px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.admin-interface .language-chooser {
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.admin-interface .language-chooser {
|
||||||
|
position: static;
|
||||||
|
float: right;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser-hidden-form {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser-select-form {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1,
|
||||||
|
.admin-interface.login #header h1,
|
||||||
|
.admin-interface.login #header h1 a {
|
||||||
|
color: var(--admin-interface-title-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1 a {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1 .logo.default {
|
||||||
|
background-color: transparent;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: 104px 36px;
|
||||||
|
background-image: var(--admin-interface-logo-default-background-image);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #branding h1 img.logo,
|
||||||
|
.admin-interface.login #header #branding h1 img.logo {
|
||||||
|
max-width: var(--admin-interface-logo-max-width);
|
||||||
|
max-height: var(--admin-interface-logo-max-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #header #user-tools a {
|
||||||
|
color: var(--admin-interface-header-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #header #user-tools a:hover,
|
||||||
|
.admin-interface #header #user-tools a:active {
|
||||||
|
color: var(--admin-interface-header-link-hover-color);
|
||||||
|
border-bottom-color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #nav-sidebar .current-app .section:link,
|
||||||
|
.admin-interface #nav-sidebar .current-app .section:visited {
|
||||||
|
color: var(--admin-interface-module-link-selected-color);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #nav-sidebar .current-app .section:focus,
|
||||||
|
.admin-interface #nav-sidebar .current-app .section:hover {
|
||||||
|
color: var(--admin-interface-module-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #nav-sidebar .current-model {
|
||||||
|
background: var(--admin-interface-module-background-selected-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist table tbody tr.selected {
|
||||||
|
background-color: var(--admin-interface-module-background-selected-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module h2,
|
||||||
|
.admin-interface .module caption,
|
||||||
|
.admin-interface .module.filtered h2 {
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module a.section:link,
|
||||||
|
.admin-interface .module a.section:visited {
|
||||||
|
color: var(--admin-interface-module-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module a.section:active,
|
||||||
|
.admin-interface .module a.section:hover {
|
||||||
|
color: var(--admin-interface-module-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div.breadcrumbs {
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div.breadcrumbs a {
|
||||||
|
color: var(--admin-interface-module-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div.breadcrumbs a:active,
|
||||||
|
.admin-interface div.breadcrumbs a:focus,
|
||||||
|
.admin-interface div.breadcrumbs a:hover {
|
||||||
|
color: var(--admin-interface-module-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface fieldset.collapse a.collapse-toggle,
|
||||||
|
.admin-interface fieldset.collapse.collapsed a.collapse-toggle,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module a.collapse-toggle,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module.collapsed a.collapse-toggle {
|
||||||
|
color: var(--admin-interface-module-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface fieldset.collapse a.collapse-toggle:hover,
|
||||||
|
.admin-interface fieldset.collapse a.collapse-toggle:active,
|
||||||
|
.admin-interface fieldset.collapse.collapsed a.collapse-toggle:hover,
|
||||||
|
.admin-interface fieldset.collapse.collapsed a.collapse-toggle:active,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module a.collapse-toggle:hover,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module a.collapse-toggle:active,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module.collapsed a.collapse-toggle:hover,
|
||||||
|
.admin-interface .inline-group .inline-related fieldset.module.collapsed a.collapse-toggle:active {
|
||||||
|
color: var(--admin-interface-module-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group h2 {
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .selector .selector-chosen h2 {
|
||||||
|
border-color: var(--admin-interface-module-background-color);
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .selector .selector-available h2,
|
||||||
|
.admin-interface .selector .selector-chosen h2 {
|
||||||
|
border-bottom-left-radius: 0px;
|
||||||
|
border-bottom-right-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .selector a.selector-chooseall:focus,
|
||||||
|
.admin-interface .selector a.selector-chooseall:hover,
|
||||||
|
.admin-interface .selector a.selector-clearall:focus,
|
||||||
|
.admin-interface .selector a.selector-clearall:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a:link,
|
||||||
|
.admin-interface a:visited {
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface thead th a,
|
||||||
|
.admin-interface thead th a:link,
|
||||||
|
.admin-interface thead th a:visited,
|
||||||
|
.admin-interface thead th a:focus,
|
||||||
|
.admin-interface thead th a:hover {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .button,
|
||||||
|
.admin-interface input[type=submit],
|
||||||
|
.admin-interface input[type=button],
|
||||||
|
.admin-interface .submit-row input,
|
||||||
|
.admin-interface a.button {
|
||||||
|
background: var(--admin-interface-save-button-background-color);
|
||||||
|
color: var(--admin-interface-save-button-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .button:active,
|
||||||
|
.admin-interface .button:focus,
|
||||||
|
.admin-interface .button:hover,
|
||||||
|
.admin-interface input[type=submit]:active,
|
||||||
|
.admin-interface input[type=submit]:focus,
|
||||||
|
.admin-interface input[type=submit]:hover,
|
||||||
|
.admin-interface input[type=button]:active,
|
||||||
|
.admin-interface input[type=button]:focus,
|
||||||
|
.admin-interface input[type=button]:hover {
|
||||||
|
background: var(--admin-interface-save-button-background-hover-color);
|
||||||
|
color: var(--admin-interface-save-button-text-color);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .button.default,
|
||||||
|
.admin-interface input[type=submit].default,
|
||||||
|
.admin-interface .submit-row input.default {
|
||||||
|
background: var(--admin-interface-save-button-background-color);
|
||||||
|
color: var(--admin-interface-save-button-text-color);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .button.default:active,
|
||||||
|
.admin-interface .button.default:focus,
|
||||||
|
.admin-interface .button.default:hover,
|
||||||
|
.admin-interface input[type=submit].default:active,
|
||||||
|
.admin-interface input[type=submit].default:focus,
|
||||||
|
.admin-interface input[type=submit].default:hover,
|
||||||
|
.admin-interface.delete-confirmation form .cancel-link:hover {
|
||||||
|
background: var(--admin-interface-save-button-background-hover-color);
|
||||||
|
color: var(--admin-interface-save-button-text-color);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .submit-row a.deletelink:link,
|
||||||
|
.admin-interface .submit-row a.deletelink:visited,
|
||||||
|
.admin-interface.delete-confirmation form input[type="submit"] {
|
||||||
|
background: var(--admin-interface-delete-button-background-color);
|
||||||
|
color: var(--admin-interface-delete-button-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .submit-row a.deletelink:hover,
|
||||||
|
.admin-interface.delete-confirmation form input[type="submit"]:hover {
|
||||||
|
background: var(--admin-interface-delete-button-background-hover-color);
|
||||||
|
color: var(--admin-interface-delete-button-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a,
|
||||||
|
.admin-interface .paginator a:link,
|
||||||
|
.admin-interface .paginator a:visited,
|
||||||
|
.admin-interface .paginator .this-page {
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a,
|
||||||
|
.admin-interface .paginator a:link,
|
||||||
|
.admin-interface .paginator a:visited {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a:hover,
|
||||||
|
.admin-interface .paginator a:active {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator .this-page {
|
||||||
|
background-color: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a.showall,
|
||||||
|
.admin-interface .paginator a.showall:link,
|
||||||
|
.admin-interface .paginator a.showall:visited {
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .paginator a.showall:hover,
|
||||||
|
.admin-interface .paginator a.showall:active {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* list-filter sticky */
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.admin-interface.list-filter-sticky .module.filtered #changelist-filter {
|
||||||
|
position: sticky;
|
||||||
|
top: 30px;
|
||||||
|
float: right;
|
||||||
|
z-index: 30;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
height: 100%;
|
||||||
|
max-height: calc(100vh - 60px);
|
||||||
|
}
|
||||||
|
.admin-interface.list-filter-sticky.sticky-pagination .module.filtered #changelist-filter {
|
||||||
|
max-height: calc(100vh - 125px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* feature not available for django < 3.1.2 */
|
||||||
|
.admin-interface.list-filter-sticky .module.filtered #toolbar + #changelist-filter {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
z-index: 30;
|
||||||
|
max-height: calc(100vh - 105px);
|
||||||
|
}
|
||||||
|
.admin-interface.list-filter-sticky.sticky-pagination .module.filtered #toolbar + #changelist-filter {
|
||||||
|
max-height: calc(100vh - 170px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter {
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter h3#changelist-filter-clear {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a {
|
||||||
|
font-size: 13px;
|
||||||
|
margin: .3em 0;
|
||||||
|
padding: 0 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a:focus,
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a:hover,
|
||||||
|
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:focus,
|
||||||
|
.admin-interface .module.filtered #changelist-filter #changelist-filter-clear a:hover {
|
||||||
|
color: #666;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter .changelist-filter-clear a span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter li a:focus,
|
||||||
|
.admin-interface .module.filtered #changelist-filter li a:hover {
|
||||||
|
color: #666;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter h3.active {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter ul.active li.selected {
|
||||||
|
color: var(--admin-interface-module-text-color);
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
margin-left: -10px;
|
||||||
|
padding-left: 5px;
|
||||||
|
margin-right: -10px;
|
||||||
|
border-left: 5px solid var(--admin-interface-module-background-color);
|
||||||
|
border-right: 5px solid var(--admin-interface-module-background-color);
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter ul.active li.selected a,
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter ul.active li.selected a:link,
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter ul.active li.selected a:visited,
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter ul.active li.selected a:focus,
|
||||||
|
.admin-interface.list-filter-highlight .module.filtered #changelist-filter ul.active li.selected a:hover {
|
||||||
|
background: inherit;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.filtered #changelist-filter li.selected a,
|
||||||
|
.admin-interface .module.filtered #changelist-filter li.selected a:link,
|
||||||
|
.admin-interface .module.filtered #changelist-filter li.selected a:visited,
|
||||||
|
.admin-interface .module.filtered #changelist-filter li.selected a:focus,
|
||||||
|
.admin-interface .module.filtered #changelist-filter li.selected a:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* begin fix issue #11 - Inline border bottom should not be rounded */
|
||||||
|
.admin-interface .module h2,
|
||||||
|
.admin-interface.dashboard .module caption,
|
||||||
|
.admin-interface #nav-sidebar .module th,
|
||||||
|
.admin-interface #nav-sidebar .module caption,
|
||||||
|
.admin-interface .module.filtered h2 {
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group h2 {
|
||||||
|
border-bottom-left-radius: 0px;
|
||||||
|
border-bottom-right-radius: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .module.collapse.collapsed h2 {
|
||||||
|
/* fix collapsed inlines rounded bottom borders */
|
||||||
|
border-bottom-left-radius: var(--admin-interface-module-border-radius);
|
||||||
|
border-bottom-right-radius: var(--admin-interface-module-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* end fix */
|
||||||
|
|
||||||
|
.admin-interface #content-related {
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
|
||||||
|
background-color: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #toggle-nav-sidebar {
|
||||||
|
border-top-right-radius: var(--admin-interface-module-border-radius);
|
||||||
|
border-bottom-right-radius: var(--admin-interface-module-border-radius);
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #toggle-nav-sidebar:focus,
|
||||||
|
.admin-interface #toggle-nav-sidebar:hover,
|
||||||
|
.admin-interface #toggle-nav-sidebar:active {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .calendar td.selected a,
|
||||||
|
.admin-interface .calendar td a:active,
|
||||||
|
.admin-interface .calendar td a:focus,
|
||||||
|
.admin-interface .calendar td a:hover,
|
||||||
|
.admin-interface .timelist a:active,
|
||||||
|
.admin-interface .timelist a:focus,
|
||||||
|
.admin-interface .timelist a:hover {
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .calendarbox .calendarnav-previous,
|
||||||
|
.admin-interface .calendarbox .calendarnav-next {
|
||||||
|
transition: none;
|
||||||
|
filter: invert(100%);
|
||||||
|
}
|
||||||
126
backend/staticfiles/admin_interface/css/ckeditor.css
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
ckeditor + light theme
|
||||||
|
https://github.com/Ikimea/ckeditor-light-theme
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface .cke {
|
||||||
|
border: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_inner,
|
||||||
|
.admin-interface .cke_wysiwyg_frame {
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_inner {
|
||||||
|
border: 1px solid #CCCCCC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_chrome {
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_top {
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-top: none;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_toolgroup {
|
||||||
|
background: none;
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_bottom {
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-top: 1px solid #EEEEEE;
|
||||||
|
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_source {
|
||||||
|
padding: 13px 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a.cke_button,
|
||||||
|
.admin-interface a.cke_button:active,
|
||||||
|
.admin-interface a.cke_button:hover,
|
||||||
|
.admin-interface a.cke_button:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
-moz-box-shadow: none;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
background-image: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a.cke_button:active,
|
||||||
|
.admin-interface a.cke_button:hover,
|
||||||
|
.admin-interface a.cke_button:focus {
|
||||||
|
background-color: #E8E8E8 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a.cke_button.cke_button_on {
|
||||||
|
background-color: #CCCCCC !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a.cke_button.cke_button_disabled {
|
||||||
|
background-color: transparent !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_resizer {
|
||||||
|
border-color: transparent #666666 transparent transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px){
|
||||||
|
|
||||||
|
.admin-interface .django-ckeditor-widget,
|
||||||
|
.admin-interface .cke {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_top {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_toolbar {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .cke_contents {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabular .django-ckeditor-widget,
|
||||||
|
.admin-interface .tabular .cke {
|
||||||
|
width: 400px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabular .cke_contents {
|
||||||
|
height: 90px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
95
backend/staticfiles/admin_interface/css/form-controls.css
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/* sticky pagination */
|
||||||
|
|
||||||
|
.admin-interface.sticky-pagination.change-list #content-main {
|
||||||
|
padding-bottom: 4.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.sticky-pagination.change-list .paginator {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 40;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top: 1px solid #EEEEEE !important;
|
||||||
|
border-bottom: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.sticky-pagination.change-list.popup .paginator {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:768px) {
|
||||||
|
.admin-interface.sticky-pagination.change-list:not(.popup) .paginator {
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1024px) {
|
||||||
|
.admin-interface.sticky-pagination.change-list:not(.popup) .paginator {
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1280px) {
|
||||||
|
.admin-interface.sticky-pagination.change-list:not(.popup) #main.shifted > #nav-sidebar + .content .paginator {
|
||||||
|
width: calc(100% - 360px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sticky submit */
|
||||||
|
|
||||||
|
@media (min-width:768px) {
|
||||||
|
.admin-interface.sticky-submit.change-form #content-main {
|
||||||
|
padding-bottom: 4.375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.sticky-submit.change-form .submit-row:last-of-type {
|
||||||
|
width: 100%;
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 40;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
border-radius: 0;
|
||||||
|
border-top: 1px solid #EEEEEE;
|
||||||
|
border-bottom: none !important;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.sticky-submit.change-form.popup .submit-row:last-of-type {
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.sticky-submit.change-form:not(.popup) .submit-row:last-of-type {
|
||||||
|
padding-left: 30px;
|
||||||
|
padding-right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1024px) {
|
||||||
|
.admin-interface.sticky-submit.change-form:not(.popup) .submit-row:last-of-type {
|
||||||
|
padding-left: 40px;
|
||||||
|
padding-right: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width:1280px) {
|
||||||
|
.admin-interface.sticky-submit.change-form:not(.popup) #main.shifted > #nav-sidebar + .content .submit-row:last-of-type {
|
||||||
|
width: calc(100% - 359px);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/* Fix left/right scrolling broken with django-import-export #165 */
|
||||||
|
.admin-interface table.import-preview {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
247
backend/staticfiles/admin_interface/css/jquery.ui.tabs.css
vendored
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* jQuery UI CSS Framework
|
||||||
|
* Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
|
||||||
|
* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses.
|
||||||
|
* http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/base/jquery.ui.core.css
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
backward compatibility:
|
||||||
|
.ui-tabs-selected: jquery ui < 1.10
|
||||||
|
.ui-tabs-active classes jquery ui >= 1.10
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Layout helpers
|
||||||
|
----------------------------------*/
|
||||||
|
.ui-helper-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-hidden-accessible {
|
||||||
|
position: absolute;
|
||||||
|
left: -99999999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-reset {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
line-height: 1.3;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 100%;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-clearfix:after {
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-clearfix {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* required comment for clearfix to work in Opera \*/
|
||||||
|
* html .ui-helper-clearfix {
|
||||||
|
height: 1%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-clearfix {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-helper-zfix {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
filter: Alpha(Opacity=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-state-disabled {
|
||||||
|
cursor: default !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-icon {
|
||||||
|
display: block;
|
||||||
|
text-indent: -99999px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/themes/base/jquery.ui.tabs.css */
|
||||||
|
.ui-widget-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs {
|
||||||
|
position: relative;
|
||||||
|
padding: .2em;
|
||||||
|
zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
|
||||||
|
.ui-tabs .ui-tabs-nav {
|
||||||
|
margin: 0;
|
||||||
|
padding: .2em .2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs .ui-tabs-nav li {
|
||||||
|
list-style: none;
|
||||||
|
float: left;
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
margin: 0 .2em 1px 0;
|
||||||
|
border-bottom: 0 !important;
|
||||||
|
padding: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs .ui-tabs-nav li a {
|
||||||
|
float: left;
|
||||||
|
padding: .5em 1em;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs .ui-tabs-nav li.ui-tabs-active, .ui-tabs .ui-tabs-nav li.ui-tabs-selected {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
|
||||||
|
.ui-tabs .ui-tabs-panel {
|
||||||
|
display: block;
|
||||||
|
border-width: 0;
|
||||||
|
padding: 1em 1.4em;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-tabs .ui-tabs-hide {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Custom tabs theme */
|
||||||
|
.admin-interface .ui-tabs {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs,
|
||||||
|
.admin-interface .ui-tabs .ui-widget-header,
|
||||||
|
.admin-interface .ui-tabs .ui-widget-header .ui-state-default {
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-nav {
|
||||||
|
padding: 10px 0 0 10px;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-nav li {
|
||||||
|
margin: 0 0 0 -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-nav li.required {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-nav li a {
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
border-bottom: none;
|
||||||
|
color: #666666;
|
||||||
|
padding: 7px 14px 8px 14px;
|
||||||
|
margin-top: 1px;
|
||||||
|
-moz-border-radius-topright: 4px;
|
||||||
|
-webkit-border-top-right-radius: 4px;
|
||||||
|
-moz-border-radius-topleft: 4px;
|
||||||
|
-webkit-border-top-left-radius: 4px;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
|
||||||
|
padding: 8px 14px 8px 14px;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
color: var(--admin-interface-module-background-color);
|
||||||
|
border-bottom: 1px solid #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-panel {
|
||||||
|
border: 1px solid #eeeeee;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular .ui-tabs .ui-tabs-panel {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular .ui-tabs .ui-tabs-nav {
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular tr td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular tr.has_original td.original,
|
||||||
|
.admin-interface .inline-group .tabular tr td.delete {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular .datetime > input {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .inline-group .tabular .datetime br {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist .row1:not(.selected):hover,
|
||||||
|
.admin-interface #changelist .row2:not(.selected):hover {
|
||||||
|
background: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .row2 {
|
||||||
|
background: #fcfcfc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .row2 .ui-tabs .ui-tabs-nav li a {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border: 1px solid #ebebeb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-active a,
|
||||||
|
.admin-interface .row2 .ui-tabs .ui-tabs-nav li.ui-tabs-selected a {
|
||||||
|
background-color: #fcfcfc;
|
||||||
|
border-bottom: 1px solid #fcfcfc;
|
||||||
|
}
|
||||||
27
backend/staticfiles/admin_interface/css/json-widget.css
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
django-json-widget support
|
||||||
|
https://github.com/jmrivas86/django-json-widget
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface div.jsoneditor {
|
||||||
|
border: 1px solid var(--admin-interface-module-background-color);
|
||||||
|
border-radius: var(--admin-interface-jsoneditor-border-radius);
|
||||||
|
overflow: var(--admin-interface-jsoneditor-overflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div.jsoneditor-menu {
|
||||||
|
background-color: var(--admin-interface-module-background-color);
|
||||||
|
border-bottom: 1px solid var(--admin-interface-module-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div.jsoneditor-menu a.jsoneditor-poweredBy {
|
||||||
|
color: var(--admin-interface-module-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div.jsoneditor-contextmenu ul li button.jsoneditor-selected,
|
||||||
|
.admin-interface div.jsoneditor-contextmenu ul li button.jsoneditor-selected:focus,
|
||||||
|
.admin-interface div.jsoneditor-contextmenu ul li button.jsoneditor-selected:hover {
|
||||||
|
background-color: var(--admin-interface-module-background-selected-color);
|
||||||
|
color: #000000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
72
backend/staticfiles/admin_interface/css/language-chooser.css
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
.admin-interface .language-chooser {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 15px;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.admin-interface .language-chooser {
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.admin-interface .language-chooser {
|
||||||
|
position: static;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser .language-chooser-hidden-form {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser .language-chooser-select-form {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser select {
|
||||||
|
width: auto;
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser.minimal .language-chooser-select-form::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
top: 50%;
|
||||||
|
border: solid var(--admin-interface-header-text-color);
|
||||||
|
border-width: 0px 0px 1px 1px;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 2px;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
-webkit-transform: rotate(-45deg);
|
||||||
|
pointer-events: none;
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser.minimal .language-chooser-select-form:hover select {
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
color: var(--admin-interface-header-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .language-chooser.minimal select {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
||||||
|
border-radius: 0;
|
||||||
|
color: var(--admin-interface-header-link-color);
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
height: auto;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 15px 0 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
list-filter-dropdown
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface #changelist-filter .list-filter-dropdown {
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist-filter h2 + .list-filter-dropdown,
|
||||||
|
.admin-interface #changelist-filter .list-filter-dropdown + .list-filter-dropdown {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist-filter .list-filter-dropdown h3 {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist-filter .list-filter-dropdown select {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.list-filter-highlight #changelist-filter .list-filter-dropdown h3.active + div select {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
17
backend/staticfiles/admin_interface/css/modeltranslation.css
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
django-modeltranslation support
|
||||||
|
https://github.com/deschler/django-modeltranslation
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface #content h1 select {
|
||||||
|
text-transform: uppercase;
|
||||||
|
margin-left: 15px;
|
||||||
|
min-width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-panel[id^=tab_id_] {
|
||||||
|
border: none;
|
||||||
|
border-top: 1px solid #eeeeee;
|
||||||
|
padding: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
25
backend/staticfiles/admin_interface/css/rangefilter.css
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
.admin-interface #changelist-filter .admindatefilter {
|
||||||
|
border-bottom: 1px solid var(--hairline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist-filter .admindatefilter .button,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter .submit-row input,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter a.button,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter input[type="submit"],
|
||||||
|
.admin-interface #changelist-filter .admindatefilter input[type="button"],
|
||||||
|
.admin-interface #changelist-filter .admindatefilter input[type="reset"] {
|
||||||
|
background: var(--admin-interface-module-background-color);
|
||||||
|
color: var(--admin-interface-module-link-color);
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #changelist-filter .admindatefilter .button:hover,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter .submit-row input:hover,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter a.button:hover,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter input[type="submit"]:hover,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter input[type="button"]:hover,
|
||||||
|
.admin-interface #changelist-filter .admindatefilter input[type="reset"]:hover {
|
||||||
|
color: var(--admin-interface-module-link-hover-color);
|
||||||
|
}
|
||||||
10
backend/staticfiles/admin_interface/css/recent-actions.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.admin-interface.dashboard #content {
|
||||||
|
width: auto;
|
||||||
|
max-width: 600px;
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.dashboard #content #recent-actions-module {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
82
backend/staticfiles/admin_interface/css/related-modal.css
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
related modal + magnific popup customization
|
||||||
|
https://github.com/dimsemenov/Magnific-Popup
|
||||||
|
*/
|
||||||
|
.admin-interface .related-modal.mfp-bg {
|
||||||
|
background-color: var(--admin-interface-related-modal-background-color);
|
||||||
|
opacity: var(--admin-interface-related-modal-background-opacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal .mfp-content {
|
||||||
|
height: 100%;
|
||||||
|
-webkit-box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
-moz-box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
box-shadow: 0px 5px 30px 0px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal .mfp-container {
|
||||||
|
padding: 80px 80px 80px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal__nested .mfp-container {
|
||||||
|
padding: 40px 80px 40px 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.admin-interface .related-modal .mfp-container {
|
||||||
|
padding: 80px 20px 80px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal__nested .mfp-container {
|
||||||
|
padding: 40px 40px 40px 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-height: 640px) {
|
||||||
|
.admin-interface .related-modal .mfp-container {
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal__nested .mfp-container {
|
||||||
|
padding: 40px 40px 40px 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal .related-modal-iframe-container {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: var(--admin-interface-related-modal-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal #related-modal-iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
background-size: 30px 30px;
|
||||||
|
background-image: url("data:image/svg+xml;utf8,<?xml version='1.0' encoding='utf-8'?><svg width='30px' height='30px' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid' class='uil-ring-alt'><rect x='0' y='0' width='100' height='100' fill='none' class='bk'></rect><circle cx='50' cy='50' r='40' stroke='%23eeeeee' fill='none' stroke-width='6' stroke-linecap='round'></circle><circle cx='50' cy='50' r='40' stroke='%23aaaaaa' fill='none' stroke-width='6' stroke-linecap='round'><animate attributeName='stroke-dashoffset' dur='2s' repeatCount='indefinite' from='0' to='500'></animate><animate attributeName='stroke-dasharray' dur='2s' repeatCount='indefinite' values='150 100;1 250;150 100'></animate></circle></svg>");
|
||||||
|
border: none;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal .mfp-close {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
opacity: 1.0;
|
||||||
|
color: rgba(0, 0, 0, 0.4);
|
||||||
|
display: var(--admin-interface-related-modal-close-button-display);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .related-modal .mfp-close:hover,
|
||||||
|
.admin-interface .related-modal .mfp-close:active {
|
||||||
|
color: rgba(0, 0, 0, 0.6);
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
34
backend/staticfiles/admin_interface/css/rtl.css
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[dir="rtl"] .admin-interface,
|
||||||
|
[dir="rtl"] .admin-interface * {
|
||||||
|
font-family: 'Vazir', sans-serif !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .admin-interface .main .toggle-nav-sidebar.sticky {
|
||||||
|
left: auto !important;
|
||||||
|
right: 0px !important;
|
||||||
|
margin-right: 0px !important;
|
||||||
|
margin-left: 10px;
|
||||||
|
border: 1px solid #eaeaea !important;
|
||||||
|
border-right: none !important;
|
||||||
|
border-top-right-radius: 0px !important;
|
||||||
|
border-bottom-right-radius: 0px !important;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
box-shadow: -4px 2px 8px -2px #DBDBDB !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .admin-interface #main.shifted > #toggle-nav-sidebar {
|
||||||
|
right: 359px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .admin-interface #main > #nav-sidebar {
|
||||||
|
margin-right: -360px !important;
|
||||||
|
margin-left: 0px !important;
|
||||||
|
right: -320px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[dir="rtl"] .admin-interface #main.shifted > #nav-sidebar {
|
||||||
|
border-left: 1px solid #eaeaea;
|
||||||
|
margin-right: 0px !important;
|
||||||
|
padding: 40px 0px 40px 40px !important;
|
||||||
|
}
|
||||||
67
backend/staticfiles/admin_interface/css/sorl-thumbnail.css
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
sorl-thumbnail - improved AdminImageMixin widget layout
|
||||||
|
https://github.com/mariocesar/sorl-thumbnail
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface a.thumbnail + a {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a.thumbnail + a + input[type="checkbox"] {
|
||||||
|
margin: 10px 0px 10px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px){
|
||||||
|
.admin-interface a.thumbnail + a {
|
||||||
|
display: block;
|
||||||
|
margin-top: 3px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.admin-interface a.thumbnail + a + input[type="checkbox"] {
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface a.thumbnail ~ label {
|
||||||
|
color: #333;
|
||||||
|
font-size: 11px;
|
||||||
|
display: inline;
|
||||||
|
float: none;
|
||||||
|
margin-left: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.change-form div[style="float:left"] {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #666;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px){
|
||||||
|
.admin-interface.change-form div[style="float:left"] {
|
||||||
|
font-size: 12px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .aligned .form-row a.thumbnail ~ input[type="file"] {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width:767px){
|
||||||
|
.admin-interface .aligned .form-row a.thumbnail ~ input[type="file"] {
|
||||||
|
width: auto;
|
||||||
|
padding: 0px;
|
||||||
|
display: block;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div[style="float:left"] {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface div[style="float:left"] + div.help {
|
||||||
|
margin-top: 0px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
200
backend/staticfiles/admin_interface/css/streamfield.css
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
django-streamfield support
|
||||||
|
https://github.com/raagin/django-streamfield/
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface .form-row.field-stream {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .form-row.field-stream label[for=id_stream] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app {
|
||||||
|
clear: both;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-help-text {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-help-text .stream-help-text__title {
|
||||||
|
align-self: flex-end;
|
||||||
|
user-select: none;
|
||||||
|
padding: 8px;
|
||||||
|
padding-right: 0;
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-help-text .stream-help-text__title:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-help-text .stream-help-text__content {
|
||||||
|
background: var(--admin-interface-module-background-selected-color);
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
border: 1px solid rgba(0,0,0,0.1);
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-help-text .stream-help-text__content > ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .collapse-handler {
|
||||||
|
user-select: none;
|
||||||
|
padding: 8px;
|
||||||
|
padding-right: 0;
|
||||||
|
margin: 0 0 5px 0;
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .collapse-handler:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block {
|
||||||
|
position: relative;
|
||||||
|
box-shadow: none;
|
||||||
|
border: 1px solid rgba(0,0,0,0.1);
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block,
|
||||||
|
.admin-interface .streamfield_app .streamfield-models.collapsed .stream-model-block {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 10px 10px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title span {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle {
|
||||||
|
position: static;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle .block-move,
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle .block-delete {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
font-weight: normal;
|
||||||
|
background: none;
|
||||||
|
flex-shrink: 0;
|
||||||
|
color: inherit;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle .block-move {
|
||||||
|
cursor: move; /* fallback if grab cursor is unsupported */
|
||||||
|
cursor: grab;
|
||||||
|
cursor: -moz-grab;
|
||||||
|
cursor: -webkit-grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle .block-move:before {
|
||||||
|
content: "↕";
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .streamblock__block__title .streamblock__block-handle .block-delete:before {
|
||||||
|
content: "×";
|
||||||
|
display: block;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .block-fields > div {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .stream-model-block__content {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-model-block .stream-model-block__content.no-subblocks.abstract-block {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-insert-new-block {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-insert-new-block .add-new-block-button {
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-insert-new-block .add-new-block-button:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-insert-new-block ul {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-insert-new-block ul li {
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 12px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-btn {
|
||||||
|
font-weight: normal;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: var(--admin-interface-generic-link-color);
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-btn:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .streamfield_app .stream-insert-new-block ul li .stream-btn {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
37
backend/staticfiles/admin_interface/css/tabbed-admin.css
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
django-tabbed-admin support
|
||||||
|
https://github.com/omji/django-tabbed-admin
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Hide tabs until ready */
|
||||||
|
/*
|
||||||
|
.admin-interface #tabs ul {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface #tabs ul.ui-tabs-nav {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .module.aligned:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .module.aligned:last-child .form-row:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 350px){
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .vTextField,
|
||||||
|
.admin-interface .inline-related .vTextField {
|
||||||
|
width: 17em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px){
|
||||||
|
/* fix horizontal overflow - responsive.css:563 */
|
||||||
|
.admin-interface .ui-tabs .ui-tabs-panel[id^=tabs] .aligned .form-row > div:not([class]) {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
.admin-interface .tabbed-changeform-tabs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
scrollbar-width: thin;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@-moz-document url-prefix() {
|
||||||
|
.admin-interface .tabbed-changeform-tabs {
|
||||||
|
padding-bottom: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
border-radius: var(--admin-interface-module-border-radius);
|
||||||
|
border-bottom-left-radius: 0px;
|
||||||
|
border-bottom-right-radius: 0px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
flex-grow: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 10px 15px;
|
||||||
|
margin: 0;
|
||||||
|
background-color: var(--admin-interface-module-header-text-color);
|
||||||
|
color: var(--admin-interface-generic-link-color);
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: bold;
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink + .tabbed-changeform-tablink {
|
||||||
|
margin-left: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink:hover {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink:focus {
|
||||||
|
color: var(--admin-interface-generic-link-hover-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabs .tabbed-changeform-tablink.active {
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-bottom: 1px solid transparent;
|
||||||
|
color: var(--admin-interface-generic-link-active-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabs-remaining-space {
|
||||||
|
flex: 1;
|
||||||
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabcontent {
|
||||||
|
display: none;
|
||||||
|
padding: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface .tabbed-changeform-tabcontent.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
3
backend/staticfiles/admin_interface/css/tinymce.css
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.admin-interface textarea.tinymce ~ p.help {
|
||||||
|
margin-top:5px !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,913 @@
|
|||||||
|
/**
|
||||||
|
* @license MIT or GPL-2.0
|
||||||
|
* @fileOverview Favico animations
|
||||||
|
* @author Miroslav Magda, http://blog.ejci.net
|
||||||
|
* @source: https://github.com/ejci/favico.js
|
||||||
|
* @version 0.3.10
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new favico instance
|
||||||
|
* @param {Object} Options
|
||||||
|
* @return {Object} Favico object
|
||||||
|
* @example
|
||||||
|
* var favico = new Favico({
|
||||||
|
* bgColor : '#d00',
|
||||||
|
* textColor : '#fff',
|
||||||
|
* fontFamily : 'sans-serif',
|
||||||
|
* fontStyle : 'bold',
|
||||||
|
* type : 'circle',
|
||||||
|
* position : 'down',
|
||||||
|
* animation : 'slide',
|
||||||
|
* elementId: false,
|
||||||
|
* element: null,
|
||||||
|
* dataUrl: function(url){},
|
||||||
|
* win: window
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
var Favico = (function (opt) {
|
||||||
|
'use strict';
|
||||||
|
opt = (opt) ? opt : {};
|
||||||
|
var _def = {
|
||||||
|
bgColor: '#d00',
|
||||||
|
textColor: '#fff',
|
||||||
|
fontFamily: 'sans-serif', //Arial,Verdana,Times New Roman,serif,sans-serif,...
|
||||||
|
fontStyle: 'bold', //normal,italic,oblique,bold,bolder,lighter,100,200,300,400,500,600,700,800,900
|
||||||
|
type: 'circle',
|
||||||
|
position: 'down', // down, up, left, leftup (upleft)
|
||||||
|
animation: 'slide',
|
||||||
|
elementId: false,
|
||||||
|
element: null,
|
||||||
|
dataUrl: false,
|
||||||
|
win: window
|
||||||
|
};
|
||||||
|
var _opt, _orig, _h, _w, _canvas, _context, _img, _ready, _lastBadge, _running, _readyCb, _stop, _browser, _animTimeout, _drawTimeout, _doc;
|
||||||
|
|
||||||
|
_browser = {};
|
||||||
|
_browser.ff = typeof InstallTrigger != 'undefined';
|
||||||
|
_browser.chrome = !!window.chrome;
|
||||||
|
_browser.opera = !!window.opera || navigator.userAgent.indexOf('Opera') >= 0;
|
||||||
|
_browser.ie = /*@cc_on!@*/false;
|
||||||
|
_browser.safari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;
|
||||||
|
_browser.supported = (_browser.chrome || _browser.ff || _browser.opera);
|
||||||
|
|
||||||
|
var _queue = [];
|
||||||
|
_readyCb = function () {
|
||||||
|
};
|
||||||
|
_ready = _stop = false;
|
||||||
|
/**
|
||||||
|
* Initialize favico
|
||||||
|
*/
|
||||||
|
var init = function () {
|
||||||
|
//merge initial options
|
||||||
|
_opt = merge(_def, opt);
|
||||||
|
_opt.bgColor = hexToRgb(_opt.bgColor);
|
||||||
|
_opt.textColor = hexToRgb(_opt.textColor);
|
||||||
|
_opt.position = _opt.position.toLowerCase();
|
||||||
|
_opt.animation = (animation.types['' + _opt.animation]) ? _opt.animation : _def.animation;
|
||||||
|
|
||||||
|
_doc = _opt.win.document;
|
||||||
|
|
||||||
|
var isUp = _opt.position.indexOf('up') > -1;
|
||||||
|
var isLeft = _opt.position.indexOf('left') > -1;
|
||||||
|
|
||||||
|
//transform the animations
|
||||||
|
if (isUp || isLeft) {
|
||||||
|
for (var a in animation.types) {
|
||||||
|
for (var i = 0; i < animation.types[a].length; i++) {
|
||||||
|
var step = animation.types[a][i];
|
||||||
|
|
||||||
|
if (isUp) {
|
||||||
|
if (step.y < 0.6) {
|
||||||
|
step.y = step.y - 0.4;
|
||||||
|
} else {
|
||||||
|
step.y = step.y - 2 * step.y + (1 - step.w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLeft) {
|
||||||
|
if (step.x < 0.6) {
|
||||||
|
step.x = step.x - 0.4;
|
||||||
|
} else {
|
||||||
|
step.x = step.x - 2 * step.x + (1 - step.h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animation.types[a][i] = step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_opt.type = (type['' + _opt.type]) ? _opt.type : _def.type;
|
||||||
|
|
||||||
|
_orig = link. getIcons();
|
||||||
|
//create temp canvas
|
||||||
|
_canvas = document.createElement('canvas');
|
||||||
|
//create temp image
|
||||||
|
_img = document.createElement('img');
|
||||||
|
var lastIcon = _orig[_orig.length - 1];
|
||||||
|
if (lastIcon.hasAttribute('href')) {
|
||||||
|
_img.setAttribute('crossOrigin', 'anonymous');
|
||||||
|
//get width/height
|
||||||
|
_img.onload = function () {
|
||||||
|
_h = (_img.height > 0) ? _img.height : 32;
|
||||||
|
_w = (_img.width > 0) ? _img.width : 32;
|
||||||
|
_canvas.height = _h;
|
||||||
|
_canvas.width = _w;
|
||||||
|
_context = _canvas.getContext('2d');
|
||||||
|
icon.ready();
|
||||||
|
};
|
||||||
|
_img.setAttribute('src', lastIcon.getAttribute('href'));
|
||||||
|
} else {
|
||||||
|
_h = 32;
|
||||||
|
_w = 32;
|
||||||
|
_img.height = _h;
|
||||||
|
_img.width = _w;
|
||||||
|
_canvas.height = _h;
|
||||||
|
_canvas.width = _w;
|
||||||
|
_context = _canvas.getContext('2d');
|
||||||
|
icon.ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Icon namespace
|
||||||
|
*/
|
||||||
|
var icon = {};
|
||||||
|
/**
|
||||||
|
* Icon is ready (reset icon) and start animation (if ther is any)
|
||||||
|
*/
|
||||||
|
icon.ready = function () {
|
||||||
|
_ready = true;
|
||||||
|
icon.reset();
|
||||||
|
_readyCb();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Reset icon to default state
|
||||||
|
*/
|
||||||
|
icon.reset = function () {
|
||||||
|
//reset
|
||||||
|
if (!_ready) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_queue = [];
|
||||||
|
_lastBadge = false;
|
||||||
|
_running = false;
|
||||||
|
_context.clearRect(0, 0, _w, _h);
|
||||||
|
_context.drawImage(_img, 0, 0, _w, _h);
|
||||||
|
//_stop=true;
|
||||||
|
link.setIcon(_canvas);
|
||||||
|
//webcam('stop');
|
||||||
|
//video('stop');
|
||||||
|
window.clearTimeout(_animTimeout);
|
||||||
|
window.clearTimeout(_drawTimeout);
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Start animation
|
||||||
|
*/
|
||||||
|
icon.start = function () {
|
||||||
|
if (!_ready || _running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var finished = function () {
|
||||||
|
_lastBadge = _queue[0];
|
||||||
|
_running = false;
|
||||||
|
if (_queue.length > 0) {
|
||||||
|
_queue.shift();
|
||||||
|
icon.start();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_queue.length > 0) {
|
||||||
|
_running = true;
|
||||||
|
var run = function () {
|
||||||
|
// apply options for this animation
|
||||||
|
['type', 'animation', 'bgColor', 'textColor', 'fontFamily', 'fontStyle'].forEach(function (a) {
|
||||||
|
if (a in _queue[0].options) {
|
||||||
|
_opt[a] = _queue[0].options[a];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
animation.run(_queue[0].options, function () {
|
||||||
|
finished();
|
||||||
|
}, false);
|
||||||
|
};
|
||||||
|
if (_lastBadge) {
|
||||||
|
animation.run(_lastBadge.options, function () {
|
||||||
|
run();
|
||||||
|
}, true);
|
||||||
|
} else {
|
||||||
|
run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Badge types
|
||||||
|
*/
|
||||||
|
var type = {};
|
||||||
|
var options = function (opt) {
|
||||||
|
opt.n = ((typeof opt.n) === 'number') ? Math.abs(opt.n | 0) : opt.n;
|
||||||
|
opt.x = _w * opt.x;
|
||||||
|
opt.y = _h * opt.y;
|
||||||
|
opt.w = _w * opt.w;
|
||||||
|
opt.h = _h * opt.h;
|
||||||
|
opt.len = ("" + opt.n).length;
|
||||||
|
return opt;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate circle
|
||||||
|
* @param {Object} opt Badge options
|
||||||
|
*/
|
||||||
|
type.circle = function (opt) {
|
||||||
|
opt = options(opt);
|
||||||
|
var more = false;
|
||||||
|
if (opt.len === 2) {
|
||||||
|
opt.x = opt.x - opt.w * 0.4;
|
||||||
|
opt.w = opt.w * 1.4;
|
||||||
|
more = true;
|
||||||
|
} else if (opt.len >= 3) {
|
||||||
|
opt.x = opt.x - opt.w * 0.65;
|
||||||
|
opt.w = opt.w * 1.65;
|
||||||
|
more = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// begin patch
|
||||||
|
// draw a smaller badge without text
|
||||||
|
opt.w = 14;
|
||||||
|
opt.h = 14;
|
||||||
|
opt.x = (_w - opt.w);
|
||||||
|
opt.y = (_h - opt.h);
|
||||||
|
// end patch
|
||||||
|
|
||||||
|
_context.clearRect(0, 0, _w, _h);
|
||||||
|
_context.drawImage(_img, 0, 0, _w, _h);
|
||||||
|
_context.beginPath();
|
||||||
|
_context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.85 : 1)) + "px " + _opt.fontFamily;
|
||||||
|
_context.textAlign = 'center';
|
||||||
|
if (more) {
|
||||||
|
_context.moveTo(opt.x + opt.w / 2, opt.y);
|
||||||
|
_context.lineTo(opt.x + opt.w - opt.h / 2, opt.y);
|
||||||
|
_context.quadraticCurveTo(opt.x + opt.w, opt.y, opt.x + opt.w, opt.y + opt.h / 2);
|
||||||
|
_context.lineTo(opt.x + opt.w, opt.y + opt.h - opt.h / 2);
|
||||||
|
_context.quadraticCurveTo(opt.x + opt.w, opt.y + opt.h, opt.x + opt.w - opt.h / 2, opt.y + opt.h);
|
||||||
|
_context.lineTo(opt.x + opt.h / 2, opt.y + opt.h);
|
||||||
|
_context.quadraticCurveTo(opt.x, opt.y + opt.h, opt.x, opt.y + opt.h - opt.h / 2);
|
||||||
|
_context.lineTo(opt.x, opt.y + opt.h / 2);
|
||||||
|
_context.quadraticCurveTo(opt.x, opt.y, opt.x + opt.h / 2, opt.y);
|
||||||
|
} else {
|
||||||
|
_context.arc(opt.x + opt.w / 2, opt.y + opt.h / 2, opt.h / 2, 0, 2 * Math.PI);
|
||||||
|
}
|
||||||
|
_context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
|
||||||
|
_context.fill();
|
||||||
|
_context.closePath();
|
||||||
|
_context.beginPath();
|
||||||
|
_context.stroke();
|
||||||
|
_context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
|
||||||
|
//_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
|
||||||
|
if ((typeof opt.n) === 'number' && opt.n > 999) {
|
||||||
|
_context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000)) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
|
||||||
|
} else {
|
||||||
|
_context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
|
||||||
|
}
|
||||||
|
_context.closePath();
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Generate rectangle
|
||||||
|
* @param {Object} opt Badge options
|
||||||
|
*/
|
||||||
|
type.rectangle = function (opt) {
|
||||||
|
opt = options(opt);
|
||||||
|
var more = false;
|
||||||
|
if (opt.len === 2) {
|
||||||
|
opt.x = opt.x - opt.w * 0.4;
|
||||||
|
opt.w = opt.w * 1.4;
|
||||||
|
more = true;
|
||||||
|
} else if (opt.len >= 3) {
|
||||||
|
opt.x = opt.x - opt.w * 0.65;
|
||||||
|
opt.w = opt.w * 1.65;
|
||||||
|
more = true;
|
||||||
|
}
|
||||||
|
_context.clearRect(0, 0, _w, _h);
|
||||||
|
_context.drawImage(_img, 0, 0, _w, _h);
|
||||||
|
_context.beginPath();
|
||||||
|
_context.font = _opt.fontStyle + " " + Math.floor(opt.h * (opt.n > 99 ? 0.9 : 1)) + "px " + _opt.fontFamily;
|
||||||
|
_context.textAlign = 'center';
|
||||||
|
_context.fillStyle = 'rgba(' + _opt.bgColor.r + ',' + _opt.bgColor.g + ',' + _opt.bgColor.b + ',' + opt.o + ')';
|
||||||
|
_context.fillRect(opt.x, opt.y, opt.w, opt.h);
|
||||||
|
_context.fillStyle = 'rgba(' + _opt.textColor.r + ',' + _opt.textColor.g + ',' + _opt.textColor.b + ',' + opt.o + ')';
|
||||||
|
//_context.fillText((more) ? '9+' : opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
|
||||||
|
if ((typeof opt.n) === 'number' && opt.n > 999) {
|
||||||
|
_context.fillText(((opt.n > 9999) ? 9 : Math.floor(opt.n / 1000)) + 'k+', Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.2));
|
||||||
|
} else {
|
||||||
|
_context.fillText(opt.n, Math.floor(opt.x + opt.w / 2), Math.floor(opt.y + opt.h - opt.h * 0.15));
|
||||||
|
}
|
||||||
|
_context.closePath();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set badge
|
||||||
|
*/
|
||||||
|
var badge = function (number, opts) {
|
||||||
|
opts = ((typeof opts) === 'string' ? {
|
||||||
|
animation: opts
|
||||||
|
} : opts) || {};
|
||||||
|
_readyCb = function () {
|
||||||
|
try {
|
||||||
|
if (typeof (number) === 'number' ? (number > 0) : (number !== '')) {
|
||||||
|
var q = {
|
||||||
|
type: 'badge',
|
||||||
|
options: {
|
||||||
|
n: number
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ('animation' in opts && animation.types['' + opts.animation]) {
|
||||||
|
q.options.animation = '' + opts.animation;
|
||||||
|
}
|
||||||
|
if ('type' in opts && type['' + opts.type]) {
|
||||||
|
q.options.type = '' + opts.type;
|
||||||
|
}
|
||||||
|
['bgColor', 'textColor'].forEach(function (o) {
|
||||||
|
if (o in opts) {
|
||||||
|
q.options[o] = hexToRgb(opts[o]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
['fontStyle', 'fontFamily'].forEach(function (o) {
|
||||||
|
if (o in opts) {
|
||||||
|
q.options[o] = opts[o];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_queue.push(q);
|
||||||
|
if (_queue.length > 100) {
|
||||||
|
throw new Error('Too many badges requests in queue.');
|
||||||
|
}
|
||||||
|
icon.start();
|
||||||
|
} else {
|
||||||
|
icon.reset();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Error setting badge. Message: ' + e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_ready) {
|
||||||
|
_readyCb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set image as icon
|
||||||
|
*/
|
||||||
|
var image = function (imageElement) {
|
||||||
|
_readyCb = function () {
|
||||||
|
try {
|
||||||
|
var w = imageElement.width;
|
||||||
|
var h = imageElement.height;
|
||||||
|
var newImg = document.createElement('img');
|
||||||
|
var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
|
||||||
|
newImg.setAttribute('crossOrigin', 'anonymous');
|
||||||
|
newImg.onload=function(){
|
||||||
|
_context.clearRect(0, 0, _w, _h);
|
||||||
|
_context.drawImage(newImg, 0, 0, _w, _h);
|
||||||
|
link.setIcon(_canvas);
|
||||||
|
};
|
||||||
|
newImg.setAttribute('src', imageElement.getAttribute('src'));
|
||||||
|
newImg.height = (h / ratio);
|
||||||
|
newImg.width = (w / ratio);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Error setting image. Message: ' + e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_ready) {
|
||||||
|
_readyCb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Set the icon from a source url. Won't work with badges.
|
||||||
|
*/
|
||||||
|
var rawImageSrc = function (url) {
|
||||||
|
_readyCb = function() {
|
||||||
|
link.setIconSrc(url);
|
||||||
|
};
|
||||||
|
if (_ready) {
|
||||||
|
_readyCb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Set video as icon
|
||||||
|
*/
|
||||||
|
var video = function (videoElement) {
|
||||||
|
_readyCb = function () {
|
||||||
|
try {
|
||||||
|
if (videoElement === 'stop') {
|
||||||
|
_stop = true;
|
||||||
|
icon.reset();
|
||||||
|
_stop = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//var w = videoElement.width;
|
||||||
|
//var h = videoElement.height;
|
||||||
|
//var ratio = (w / _w < h / _h) ? (w / _w) : (h / _h);
|
||||||
|
videoElement.addEventListener('play', function () {
|
||||||
|
drawVideo(this);
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Error setting video. Message: ' + e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_ready) {
|
||||||
|
_readyCb();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Set video as icon
|
||||||
|
*/
|
||||||
|
var webcam = function (action) {
|
||||||
|
//UR
|
||||||
|
if (!window.URL || !window.URL.createObjectURL) {
|
||||||
|
window.URL = window.URL || {};
|
||||||
|
window.URL.createObjectURL = function (obj) {
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (_browser.supported) {
|
||||||
|
var newVideo = false;
|
||||||
|
navigator.getUserMedia = navigator.getUserMedia || navigator.oGetUserMedia || navigator.msGetUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
|
||||||
|
_readyCb = function () {
|
||||||
|
try {
|
||||||
|
if (action === 'stop') {
|
||||||
|
_stop = true;
|
||||||
|
icon.reset();
|
||||||
|
_stop = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
newVideo = document.createElement('video');
|
||||||
|
newVideo.width = _w;
|
||||||
|
newVideo.height = _h;
|
||||||
|
navigator.getUserMedia({
|
||||||
|
video: true,
|
||||||
|
audio: false
|
||||||
|
}, function (stream) {
|
||||||
|
newVideo.src = URL.createObjectURL(stream);
|
||||||
|
newVideo.play();
|
||||||
|
drawVideo(newVideo);
|
||||||
|
}, function () {
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error('Error setting webcam. Message: ' + e.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (_ready) {
|
||||||
|
_readyCb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var setOpt = function (key, value) {
|
||||||
|
var opts = key;
|
||||||
|
if (!(value == null && Object.prototype.toString.call(key) == '[object Object]')) {
|
||||||
|
opts = {};
|
||||||
|
opts[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var keys = Object.keys(opts);
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
if (keys[i] == 'bgColor' || keys[i] == 'textColor') {
|
||||||
|
_opt[keys[i]] = hexToRgb(opts[keys[i]]);
|
||||||
|
} else {
|
||||||
|
_opt[keys[i]] = opts[keys[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_queue.push(_lastBadge);
|
||||||
|
icon.start();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw video to context and repeat :)
|
||||||
|
*/
|
||||||
|
function drawVideo(video) {
|
||||||
|
if (video.paused || video.ended || _stop) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
//nasty hack for FF webcam (Thanks to Julian Ćwirko, kontakt@redsunmedia.pl)
|
||||||
|
try {
|
||||||
|
_context.clearRect(0, 0, _w, _h);
|
||||||
|
_context.drawImage(video, 0, 0, _w, _h);
|
||||||
|
} catch (e) {
|
||||||
|
|
||||||
|
}
|
||||||
|
_drawTimeout = setTimeout(function () {
|
||||||
|
drawVideo(video);
|
||||||
|
}, animation.duration);
|
||||||
|
link.setIcon(_canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
var link = {};
|
||||||
|
/**
|
||||||
|
* Get icons from HEAD tag or create a new <link> element
|
||||||
|
*/
|
||||||
|
link.getIcons = function () {
|
||||||
|
var elms = [];
|
||||||
|
//get link element
|
||||||
|
var getLinks = function () {
|
||||||
|
var icons = [];
|
||||||
|
var links = _doc.getElementsByTagName('head')[0].getElementsByTagName('link');
|
||||||
|
for (var i = 0; i < links.length; i++) {
|
||||||
|
if ((/(^|\s)icon(\s|$)/i).test(links[i].getAttribute('rel'))) {
|
||||||
|
icons.push(links[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return icons;
|
||||||
|
};
|
||||||
|
if (_opt.element) {
|
||||||
|
elms = [_opt.element];
|
||||||
|
} else if (_opt.elementId) {
|
||||||
|
//if img element identified by elementId
|
||||||
|
elms = [_doc.getElementById(_opt.elementId)];
|
||||||
|
elms[0].setAttribute('href', elms[0].getAttribute('src'));
|
||||||
|
} else {
|
||||||
|
//if link element
|
||||||
|
elms = getLinks();
|
||||||
|
if (elms.length === 0) {
|
||||||
|
elms = [_doc.createElement('link')];
|
||||||
|
elms[0].setAttribute('rel', 'icon');
|
||||||
|
_doc.getElementsByTagName('head')[0].appendChild(elms[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elms.forEach(function(item) {
|
||||||
|
item.setAttribute('type', 'image/png');
|
||||||
|
});
|
||||||
|
return elms;
|
||||||
|
};
|
||||||
|
link.setIcon = function (canvas) {
|
||||||
|
var url = canvas.toDataURL('image/png');
|
||||||
|
link.setIconSrc(url);
|
||||||
|
};
|
||||||
|
link.setIconSrc = function (url) {
|
||||||
|
if (_opt.dataUrl) {
|
||||||
|
//if using custom exporter
|
||||||
|
_opt.dataUrl(url);
|
||||||
|
}
|
||||||
|
if (_opt.element) {
|
||||||
|
_opt.element.setAttribute('href', url);
|
||||||
|
_opt.element.setAttribute('src', url);
|
||||||
|
} else if (_opt.elementId) {
|
||||||
|
//if is attached to element (image)
|
||||||
|
var elm = _doc.getElementById(_opt.elementId);
|
||||||
|
elm.setAttribute('href', url);
|
||||||
|
elm.setAttribute('src', url);
|
||||||
|
} else {
|
||||||
|
//if is attached to fav icon
|
||||||
|
if (_browser.ff || _browser.opera) {
|
||||||
|
//for FF we need to "recreate" element, atach to dom and remove old <link>
|
||||||
|
//var originalType = _orig.getAttribute('rel');
|
||||||
|
var old = _orig[_orig.length - 1];
|
||||||
|
var newIcon = _doc.createElement('link');
|
||||||
|
_orig = [newIcon];
|
||||||
|
//_orig.setAttribute('rel', originalType);
|
||||||
|
if (_browser.opera) {
|
||||||
|
newIcon.setAttribute('rel', 'icon');
|
||||||
|
}
|
||||||
|
newIcon.setAttribute('rel', 'icon');
|
||||||
|
newIcon.setAttribute('type', 'image/png');
|
||||||
|
_doc.getElementsByTagName('head')[0].appendChild(newIcon);
|
||||||
|
newIcon.setAttribute('href', url);
|
||||||
|
if (old.parentNode) {
|
||||||
|
old.parentNode.removeChild(old);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_orig.forEach(function(icon) {
|
||||||
|
icon.setAttribute('href', url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-5624139
|
||||||
|
//HEX to RGB convertor
|
||||||
|
function hexToRgb(hex) {
|
||||||
|
var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||||
|
hex = hex.replace(shorthandRegex, function (m, r, g, b) {
|
||||||
|
return r + r + g + g + b + b;
|
||||||
|
});
|
||||||
|
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
return result ? {
|
||||||
|
r: parseInt(result[1], 16),
|
||||||
|
g: parseInt(result[2], 16),
|
||||||
|
b: parseInt(result[3], 16)
|
||||||
|
} : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge options
|
||||||
|
*/
|
||||||
|
function merge(def, opt) {
|
||||||
|
var mergedOpt = {};
|
||||||
|
var attrname;
|
||||||
|
for (attrname in def) {
|
||||||
|
mergedOpt[attrname] = def[attrname];
|
||||||
|
}
|
||||||
|
for (attrname in opt) {
|
||||||
|
mergedOpt[attrname] = opt[attrname];
|
||||||
|
}
|
||||||
|
return mergedOpt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cross-browser page visibility shim
|
||||||
|
* http://stackoverflow.com/questions/12536562/detect-whether-a-window-is-visible
|
||||||
|
*/
|
||||||
|
function isPageHidden() {
|
||||||
|
return _doc.hidden || _doc.msHidden || _doc.webkitHidden || _doc.mozHidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @namespace animation
|
||||||
|
*/
|
||||||
|
var animation = {};
|
||||||
|
/**
|
||||||
|
* Animation "frame" duration
|
||||||
|
*/
|
||||||
|
animation.duration = 40;
|
||||||
|
/**
|
||||||
|
* Animation types (none,fade,pop,slide)
|
||||||
|
*/
|
||||||
|
animation.types = {};
|
||||||
|
animation.types.fade = [{
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.0
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.2
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.3
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.4
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.5
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.6
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.7
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.8
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 0.9
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1.0
|
||||||
|
}];
|
||||||
|
animation.types.none = [{
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}];
|
||||||
|
animation.types.pop = [{
|
||||||
|
x: 1,
|
||||||
|
y: 1,
|
||||||
|
w: 0,
|
||||||
|
h: 0,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.9,
|
||||||
|
y: 0.9,
|
||||||
|
w: 0.1,
|
||||||
|
h: 0.1,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.8,
|
||||||
|
y: 0.8,
|
||||||
|
w: 0.2,
|
||||||
|
h: 0.2,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.7,
|
||||||
|
y: 0.7,
|
||||||
|
w: 0.3,
|
||||||
|
h: 0.3,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.6,
|
||||||
|
y: 0.6,
|
||||||
|
w: 0.4,
|
||||||
|
h: 0.4,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.5,
|
||||||
|
y: 0.5,
|
||||||
|
w: 0.5,
|
||||||
|
h: 0.5,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}];
|
||||||
|
animation.types.popFade = [{
|
||||||
|
x: 0.75,
|
||||||
|
y: 0.75,
|
||||||
|
w: 0,
|
||||||
|
h: 0,
|
||||||
|
o: 0
|
||||||
|
}, {
|
||||||
|
x: 0.65,
|
||||||
|
y: 0.65,
|
||||||
|
w: 0.1,
|
||||||
|
h: 0.1,
|
||||||
|
o: 0.2
|
||||||
|
}, {
|
||||||
|
x: 0.6,
|
||||||
|
y: 0.6,
|
||||||
|
w: 0.2,
|
||||||
|
h: 0.2,
|
||||||
|
o: 0.4
|
||||||
|
}, {
|
||||||
|
x: 0.55,
|
||||||
|
y: 0.55,
|
||||||
|
w: 0.3,
|
||||||
|
h: 0.3,
|
||||||
|
o: 0.6
|
||||||
|
}, {
|
||||||
|
x: 0.50,
|
||||||
|
y: 0.50,
|
||||||
|
w: 0.4,
|
||||||
|
h: 0.4,
|
||||||
|
o: 0.8
|
||||||
|
}, {
|
||||||
|
x: 0.45,
|
||||||
|
y: 0.45,
|
||||||
|
w: 0.5,
|
||||||
|
h: 0.5,
|
||||||
|
o: 0.9
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}];
|
||||||
|
animation.types.slide = [{
|
||||||
|
x: 0.4,
|
||||||
|
y: 1,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.9,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.9,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.8,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.7,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.6,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.5,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}, {
|
||||||
|
x: 0.4,
|
||||||
|
y: 0.4,
|
||||||
|
w: 0.6,
|
||||||
|
h: 0.6,
|
||||||
|
o: 1
|
||||||
|
}];
|
||||||
|
/**
|
||||||
|
* Run animation
|
||||||
|
* @param {Object} opt Animation options
|
||||||
|
* @param {Object} cb Callabak after all steps are done
|
||||||
|
* @param {Object} revert Reverse order? true|false
|
||||||
|
* @param {Object} step Optional step number (frame bumber)
|
||||||
|
*/
|
||||||
|
animation.run = function (opt, cb, revert, step) {
|
||||||
|
var animationType = animation.types[isPageHidden() ? 'none' : _opt.animation];
|
||||||
|
if (revert === true) {
|
||||||
|
step = (typeof step !== 'undefined') ? step : animationType.length - 1;
|
||||||
|
} else {
|
||||||
|
step = (typeof step !== 'undefined') ? step : 0;
|
||||||
|
}
|
||||||
|
cb = (cb) ? cb : function () {
|
||||||
|
};
|
||||||
|
if ((step < animationType.length) && (step >= 0)) {
|
||||||
|
type[_opt.type](merge(opt, animationType[step]));
|
||||||
|
_animTimeout = setTimeout(function () {
|
||||||
|
if (revert) {
|
||||||
|
step = step - 1;
|
||||||
|
} else {
|
||||||
|
step = step + 1;
|
||||||
|
}
|
||||||
|
animation.run(opt, cb, revert, step);
|
||||||
|
}, animation.duration);
|
||||||
|
|
||||||
|
link.setIcon(_canvas);
|
||||||
|
} else {
|
||||||
|
cb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//auto init
|
||||||
|
init();
|
||||||
|
return {
|
||||||
|
badge: badge,
|
||||||
|
video: video,
|
||||||
|
image: image,
|
||||||
|
rawImageSrc: rawImageSrc,
|
||||||
|
webcam: webcam,
|
||||||
|
setOpt: setOpt,
|
||||||
|
reset: icon.reset,
|
||||||
|
browser: {
|
||||||
|
supported: _browser.supported
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// AMD / RequireJS
|
||||||
|
if (typeof define !== 'undefined' && define.amd) {
|
||||||
|
define([], function () {
|
||||||
|
return Favico;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// CommonJS
|
||||||
|
else if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = Favico;
|
||||||
|
}
|
||||||
|
// included directly via <script> tag
|
||||||
|
else {
|
||||||
|
this.Favico = Favico;
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
1
backend/staticfiles/admin_interface/favico/favico-0.3.10-patched.min.js
vendored
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
.admin-interface.foldable-apps [class^="app-"].module {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module.foldable-apps-ready {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module > table > caption {
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
/* pointer-events: none; */
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-touch-callout: none; /* iOS Safari */
|
||||||
|
-webkit-user-select: none; /* Safari */
|
||||||
|
-khtml-user-select: none; /* Konqueror HTML */
|
||||||
|
-moz-user-select: none; /* Firefox */
|
||||||
|
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||||
|
user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module > table > caption > a {
|
||||||
|
display: inline-block;
|
||||||
|
/* pointer-events: all !important; */
|
||||||
|
margin-right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module > table > caption::after {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 10;
|
||||||
|
width: auto;
|
||||||
|
height: 100%;
|
||||||
|
content: "−";
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: lighter;
|
||||||
|
text-align: center;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
pointer-events: all !important;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module > table > caption::after {
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module > table {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module.collapsed {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module.collapsed > table > caption::after {
|
||||||
|
content: "+";
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-interface.foldable-apps [class^="app-"].module.collapsed > table > tbody {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
(function() {
|
||||||
|
window.onload = function() {
|
||||||
|
for (let moduleEl of document.querySelectorAll('.admin-interface.foldable-apps [class^="app-"].module')) {
|
||||||
|
// apply collapsed value from localstorage value
|
||||||
|
let moduleAppClass = null;
|
||||||
|
let moduleCollapsedClass = 'collapsed';
|
||||||
|
moduleEl.classList.forEach(function(className) {
|
||||||
|
if (className.startsWith('app-')) {
|
||||||
|
moduleAppClass = className;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (moduleAppClass) {
|
||||||
|
let moduleAppKey = 'admin-interface.foldable-apps_' + moduleAppClass + '_collapsed';
|
||||||
|
let moduleCollapsed = Boolean(parseInt((localStorage.getItem(moduleAppKey) || 0)) || 0);
|
||||||
|
if (moduleCollapsed === true) {
|
||||||
|
moduleEl.classList.add(moduleCollapsedClass);
|
||||||
|
} else {
|
||||||
|
moduleEl.classList.remove(moduleCollapsedClass);
|
||||||
|
}
|
||||||
|
// attach click for togggle collapsed class
|
||||||
|
for (let captionEl of moduleEl.querySelectorAll('caption')) {
|
||||||
|
captionEl.onclick = function(event) {
|
||||||
|
// only when not clicking on the app name link
|
||||||
|
if (event.target.tagName.toLowerCase() === 'caption') {
|
||||||
|
moduleEl.classList.toggle(moduleCollapsedClass);
|
||||||
|
moduleCollapsed = moduleEl.classList.contains(moduleCollapsedClass);
|
||||||
|
localStorage.setItem(moduleAppKey, (moduleCollapsed ? 1 : 0));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
moduleEl.classList.add('foldable-apps-ready');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
/* Magnific Popup CSS */
|
||||||
|
.mfp-bg {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1042;
|
||||||
|
overflow: hidden;
|
||||||
|
position: fixed;
|
||||||
|
background: #0b0b0b;
|
||||||
|
opacity: 0.8; }
|
||||||
|
|
||||||
|
.mfp-wrap {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1043;
|
||||||
|
position: fixed;
|
||||||
|
outline: none !important;
|
||||||
|
-webkit-backface-visibility: hidden; }
|
||||||
|
|
||||||
|
.mfp-container {
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
|
||||||
|
.mfp-container:before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
vertical-align: middle; }
|
||||||
|
|
||||||
|
.mfp-align-top .mfp-container:before {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.mfp-content {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0 auto;
|
||||||
|
text-align: left;
|
||||||
|
z-index: 1045; }
|
||||||
|
|
||||||
|
.mfp-inline-holder .mfp-content,
|
||||||
|
.mfp-ajax-holder .mfp-content {
|
||||||
|
width: 100%;
|
||||||
|
cursor: auto; }
|
||||||
|
|
||||||
|
.mfp-ajax-cur {
|
||||||
|
cursor: progress; }
|
||||||
|
|
||||||
|
.mfp-zoom-out-cur, .mfp-zoom-out-cur .mfp-image-holder .mfp-close {
|
||||||
|
cursor: -moz-zoom-out;
|
||||||
|
cursor: -webkit-zoom-out;
|
||||||
|
cursor: zoom-out; }
|
||||||
|
|
||||||
|
.mfp-zoom {
|
||||||
|
cursor: pointer;
|
||||||
|
cursor: -webkit-zoom-in;
|
||||||
|
cursor: -moz-zoom-in;
|
||||||
|
cursor: zoom-in; }
|
||||||
|
|
||||||
|
.mfp-auto-cursor .mfp-content {
|
||||||
|
cursor: auto; }
|
||||||
|
|
||||||
|
.mfp-close,
|
||||||
|
.mfp-arrow,
|
||||||
|
.mfp-preloader,
|
||||||
|
.mfp-counter {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none; }
|
||||||
|
|
||||||
|
.mfp-loading.mfp-figure {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.mfp-hide {
|
||||||
|
display: none !important; }
|
||||||
|
|
||||||
|
.mfp-preloader {
|
||||||
|
color: #CCC;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: -0.8em;
|
||||||
|
left: 8px;
|
||||||
|
right: 8px;
|
||||||
|
z-index: 1044; }
|
||||||
|
.mfp-preloader a {
|
||||||
|
color: #CCC; }
|
||||||
|
.mfp-preloader a:hover {
|
||||||
|
color: #FFF; }
|
||||||
|
|
||||||
|
.mfp-s-ready .mfp-preloader {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
.mfp-s-error .mfp-content {
|
||||||
|
display: none; }
|
||||||
|
|
||||||
|
button.mfp-close,
|
||||||
|
button.mfp-arrow {
|
||||||
|
overflow: visible;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
display: block;
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
z-index: 1046;
|
||||||
|
box-shadow: none;
|
||||||
|
touch-action: manipulation; }
|
||||||
|
|
||||||
|
button::-moz-focus-inner {
|
||||||
|
padding: 0;
|
||||||
|
border: 0; }
|
||||||
|
|
||||||
|
.mfp-close {
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
line-height: 44px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
text-decoration: none;
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.65;
|
||||||
|
padding: 0 0 18px 10px;
|
||||||
|
color: #FFF;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 28px;
|
||||||
|
font-family: Arial, Baskerville, monospace; }
|
||||||
|
.mfp-close:hover,
|
||||||
|
.mfp-close:focus {
|
||||||
|
opacity: 1; }
|
||||||
|
.mfp-close:active {
|
||||||
|
top: 1px; }
|
||||||
|
|
||||||
|
.mfp-close-btn-in .mfp-close {
|
||||||
|
color: #333; }
|
||||||
|
|
||||||
|
.mfp-image-holder .mfp-close,
|
||||||
|
.mfp-iframe-holder .mfp-close {
|
||||||
|
color: #FFF;
|
||||||
|
right: -6px;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 6px;
|
||||||
|
width: 100%; }
|
||||||
|
|
||||||
|
.mfp-counter {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
color: #CCC;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
|
white-space: nowrap; }
|
||||||
|
|
||||||
|
.mfp-arrow {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.65;
|
||||||
|
margin: 0;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -55px;
|
||||||
|
padding: 0;
|
||||||
|
width: 90px;
|
||||||
|
height: 110px;
|
||||||
|
-webkit-tap-highlight-color: transparent; }
|
||||||
|
.mfp-arrow:active {
|
||||||
|
margin-top: -54px; }
|
||||||
|
.mfp-arrow:hover,
|
||||||
|
.mfp-arrow:focus {
|
||||||
|
opacity: 1; }
|
||||||
|
.mfp-arrow:before,
|
||||||
|
.mfp-arrow:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
margin-top: 35px;
|
||||||
|
margin-left: 35px;
|
||||||
|
border: medium inset transparent; }
|
||||||
|
.mfp-arrow:after {
|
||||||
|
border-top-width: 13px;
|
||||||
|
border-bottom-width: 13px;
|
||||||
|
top: 8px; }
|
||||||
|
.mfp-arrow:before {
|
||||||
|
border-top-width: 21px;
|
||||||
|
border-bottom-width: 21px;
|
||||||
|
opacity: 0.7; }
|
||||||
|
|
||||||
|
.mfp-arrow-left {
|
||||||
|
left: 0; }
|
||||||
|
.mfp-arrow-left:after {
|
||||||
|
border-right: 17px solid #FFF;
|
||||||
|
margin-left: 31px; }
|
||||||
|
.mfp-arrow-left:before {
|
||||||
|
margin-left: 25px;
|
||||||
|
border-right: 27px solid #3F3F3F; }
|
||||||
|
|
||||||
|
.mfp-arrow-right {
|
||||||
|
right: 0; }
|
||||||
|
.mfp-arrow-right:after {
|
||||||
|
border-left: 17px solid #FFF;
|
||||||
|
margin-left: 39px; }
|
||||||
|
.mfp-arrow-right:before {
|
||||||
|
border-left: 27px solid #3F3F3F; }
|
||||||
|
|
||||||
|
.mfp-iframe-holder {
|
||||||
|
padding-top: 40px;
|
||||||
|
padding-bottom: 40px; }
|
||||||
|
.mfp-iframe-holder .mfp-content {
|
||||||
|
line-height: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 900px; }
|
||||||
|
.mfp-iframe-holder .mfp-close {
|
||||||
|
top: -40px; }
|
||||||
|
|
||||||
|
.mfp-iframe-scaler {
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-top: 56.25%; }
|
||||||
|
.mfp-iframe-scaler iframe {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||||
|
background: #000; }
|
||||||
|
|
||||||
|
/* Main image in popup */
|
||||||
|
img.mfp-img {
|
||||||
|
width: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: block;
|
||||||
|
line-height: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 40px 0 40px;
|
||||||
|
margin: 0 auto; }
|
||||||
|
|
||||||
|
/* The shadow behind the image */
|
||||||
|
.mfp-figure {
|
||||||
|
line-height: 0; }
|
||||||
|
.mfp-figure:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 40px;
|
||||||
|
bottom: 40px;
|
||||||
|
display: block;
|
||||||
|
right: 0;
|
||||||
|
width: auto;
|
||||||
|
height: auto;
|
||||||
|
z-index: -1;
|
||||||
|
box-shadow: 0 0 8px rgba(0, 0, 0, 0.6);
|
||||||
|
background: #444; }
|
||||||
|
.mfp-figure small {
|
||||||
|
color: #BDBDBD;
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 14px; }
|
||||||
|
.mfp-figure figure {
|
||||||
|
margin: 0; }
|
||||||
|
|
||||||
|
.mfp-bottom-bar {
|
||||||
|
margin-top: -36px;
|
||||||
|
position: absolute;
|
||||||
|
top: 100%;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
cursor: auto; }
|
||||||
|
|
||||||
|
.mfp-title {
|
||||||
|
text-align: left;
|
||||||
|
line-height: 18px;
|
||||||
|
color: #F3F3F3;
|
||||||
|
word-wrap: break-word;
|
||||||
|
padding-right: 36px; }
|
||||||
|
|
||||||
|
.mfp-image-holder .mfp-content {
|
||||||
|
max-width: 100%; }
|
||||||
|
|
||||||
|
.mfp-gallery .mfp-image-holder .mfp-figure {
|
||||||
|
cursor: pointer; }
|
||||||
|
|
||||||
|
@media screen and (max-width: 800px) and (orientation: landscape), screen and (max-height: 300px) {
|
||||||
|
/**
|
||||||
|
* Remove all paddings around the image on small screen
|
||||||
|
*/
|
||||||
|
.mfp-img-mobile .mfp-image-holder {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0; }
|
||||||
|
.mfp-img-mobile img.mfp-img {
|
||||||
|
padding: 0; }
|
||||||
|
.mfp-img-mobile .mfp-figure:after {
|
||||||
|
top: 0;
|
||||||
|
bottom: 0; }
|
||||||
|
.mfp-img-mobile .mfp-figure small {
|
||||||
|
display: inline;
|
||||||
|
margin-left: 5px; }
|
||||||
|
.mfp-img-mobile .mfp-bottom-bar {
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
bottom: 0;
|
||||||
|
margin: 0;
|
||||||
|
top: auto;
|
||||||
|
padding: 3px 5px;
|
||||||
|
position: fixed;
|
||||||
|
box-sizing: border-box; }
|
||||||
|
.mfp-img-mobile .mfp-bottom-bar:empty {
|
||||||
|
padding: 0; }
|
||||||
|
.mfp-img-mobile .mfp-counter {
|
||||||
|
right: 5px;
|
||||||
|
top: 3px; }
|
||||||
|
.mfp-img-mobile .mfp-close {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 35px;
|
||||||
|
height: 35px;
|
||||||
|
line-height: 35px;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
position: fixed;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0; } }
|
||||||
|
|
||||||
|
@media all and (max-width: 900px) {
|
||||||
|
.mfp-arrow {
|
||||||
|
-webkit-transform: scale(0.75);
|
||||||
|
transform: scale(0.75); }
|
||||||
|
.mfp-arrow-left {
|
||||||
|
-webkit-transform-origin: 0;
|
||||||
|
transform-origin: 0; }
|
||||||
|
.mfp-arrow-right {
|
||||||
|
-webkit-transform-origin: 100%;
|
||||||
|
transform-origin: 100%; }
|
||||||
|
.mfp-container {
|
||||||
|
padding-left: 6px;
|
||||||
|
padding-right: 6px; } }
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
/** global: django */
|
||||||
|
|
||||||
|
if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined')
|
||||||
|
{
|
||||||
|
(function($) {
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
|
||||||
|
function dismissModal()
|
||||||
|
{
|
||||||
|
$.magnificPopup.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the function that will close the modal
|
||||||
|
function dismissRelatedObjectModal()
|
||||||
|
{
|
||||||
|
dismissModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dismissRelatedLookupModal(win, chosenId)
|
||||||
|
{
|
||||||
|
var windowRef = win;
|
||||||
|
var windowName = windowRef.name;
|
||||||
|
var widgetName = windowName.replace(/^(change|add|delete|lookup)_/, '');
|
||||||
|
var widgetEl = $('#' + widgetName);
|
||||||
|
var widgetVal = widgetEl.val();
|
||||||
|
if (widgetEl.hasClass('vManyToManyRawIdAdminField') && Boolean(widgetVal)) {
|
||||||
|
widgetEl.val(widgetVal + ', ' + chosenId);
|
||||||
|
} else {
|
||||||
|
widgetEl.val(chosenId);
|
||||||
|
}
|
||||||
|
dismissModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign functions to global variables
|
||||||
|
window.dismissRelatedObjectModal = dismissRelatedObjectModal;
|
||||||
|
window.dismissRelatedLookupPopup = dismissRelatedLookupModal;
|
||||||
|
|
||||||
|
function presentRelatedObjectModal(e)
|
||||||
|
{
|
||||||
|
var linkEl = $(this);
|
||||||
|
|
||||||
|
var href = (linkEl.attr('href') || '');
|
||||||
|
if (href === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the popup as modal
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
|
||||||
|
// remove focus from clicked link
|
||||||
|
linkEl.blur();
|
||||||
|
|
||||||
|
// use the clicked link id as iframe name
|
||||||
|
// it will be available as window.name in the loaded iframe
|
||||||
|
var iframeName = linkEl.attr('id');
|
||||||
|
var iframeSrc = href;
|
||||||
|
|
||||||
|
if (e.data.lookup !== true)
|
||||||
|
{
|
||||||
|
// browsers stop loading nested iframes having the same src url
|
||||||
|
// create a random parameter and append it to the src url to prevent it
|
||||||
|
// this workaround doesn't work with related lookup url
|
||||||
|
var iframeSrcRandom = String(Math.round(Math.random() * 999999));
|
||||||
|
if (iframeSrc.indexOf('?') === -1) {
|
||||||
|
iframeSrc += '?_modal=' + iframeSrcRandom;
|
||||||
|
} else {
|
||||||
|
iframeSrc += '&_modal=' + iframeSrcRandom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fix for django 1.7 TODO remove
|
||||||
|
if (iframeSrc.indexOf('_popup=1') === -1) {
|
||||||
|
if (iframeSrc.indexOf('?') === -1) {
|
||||||
|
iframeSrc += '?_popup=1';
|
||||||
|
} else {
|
||||||
|
iframeSrc += '&_popup=1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the iframe html
|
||||||
|
var iframeHTML = '<iframe id="related-modal-iframe" name="' + iframeName + '" src="' + iframeSrc + '"></iframe>';
|
||||||
|
var modalHTML = '<div class="related-modal-iframe-container">' + iframeHTML + '</div>';
|
||||||
|
var modalEl = $(modalHTML);
|
||||||
|
var iframeEl = modalEl.find('#related-modal-iframe');
|
||||||
|
|
||||||
|
if (e.data.lookup === true)
|
||||||
|
{
|
||||||
|
// set current window as iframe opener because
|
||||||
|
// the callback is called on the opener window
|
||||||
|
iframeEl.on('load', function() {
|
||||||
|
var iframeObj = $(this).get(0);
|
||||||
|
var iframeWindow = iframeObj.contentWindow;
|
||||||
|
iframeWindow.opener = window;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// the modal css class
|
||||||
|
var iframeInternalModalClass = 'related-modal';
|
||||||
|
|
||||||
|
// if the current window is inside an iframe, it means that it is already in a modal,
|
||||||
|
// append an additional css class to the modal to offer more customization
|
||||||
|
if (window.top !== window.self) {
|
||||||
|
iframeInternalModalClass += ' related-modal__nested';
|
||||||
|
}
|
||||||
|
|
||||||
|
// open the popup using magnific popup
|
||||||
|
$.magnificPopup.open({
|
||||||
|
mainClass: iframeInternalModalClass,
|
||||||
|
fixedContentPos: false,
|
||||||
|
showCloseBtn: true,
|
||||||
|
closeBtnInside: true,
|
||||||
|
items: {
|
||||||
|
src: modalEl,
|
||||||
|
type: 'inline'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen click events on related links
|
||||||
|
function presentRelatedObjectModalOnClickOn(selector, lookup) {
|
||||||
|
var data = {
|
||||||
|
lookup:(lookup === true ? true : false)
|
||||||
|
};
|
||||||
|
// remove potential existing click event listener
|
||||||
|
var el = $(selector);
|
||||||
|
el.removeAttr('onclick');
|
||||||
|
el.unbind('click');
|
||||||
|
el.click(data, presentRelatedObjectModal);
|
||||||
|
// listen the event on document for handling it on elements will be added to the DOM later
|
||||||
|
$(document).on('click', selector, data, presentRelatedObjectModal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign functions to global variables
|
||||||
|
window.presentRelatedObjectModal = presentRelatedObjectModal;
|
||||||
|
window.presentRelatedObjectModalOnClickOn = presentRelatedObjectModalOnClickOn;
|
||||||
|
|
||||||
|
presentRelatedObjectModalOnClickOn('a.related-widget-wrapper-link');
|
||||||
|
|
||||||
|
// raw_id_fields support
|
||||||
|
presentRelatedObjectModalOnClickOn('a.related-lookup', true);
|
||||||
|
|
||||||
|
// django-dynamic-raw-id support - #61
|
||||||
|
// https://github.com/lincolnloop/django-dynamic-raw-id
|
||||||
|
presentRelatedObjectModalOnClickOn('a.dynamic_raw_id-related-lookup', true);
|
||||||
|
|
||||||
|
// django-streamfield support
|
||||||
|
// https://github.com/raagin/django-streamfield/
|
||||||
|
presentRelatedObjectModalOnClickOn('.streamfield_app a.stream-btn[href*="_popup=1"]');
|
||||||
|
// Vanilla js for catching the click during capture phase for anticipating Vue.js listener.
|
||||||
|
document.addEventListener('click', function(event) {
|
||||||
|
// console.log('click intercepted before Vue.');
|
||||||
|
if (event.target.matches('.streamfield_app a.stream-btn[href*="_popup=1"]')) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
$(event.target).trigger('click');
|
||||||
|
}
|
||||||
|
}, { capture: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
})(django.jQuery);
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
(function (AdminInterface) {
|
||||||
|
|
||||||
|
var scope = AdminInterface;
|
||||||
|
|
||||||
|
scope.tabbedChangeForm = {
|
||||||
|
|
||||||
|
openTab: function (event, tabName) {
|
||||||
|
this.openTabByName(tabName);
|
||||||
|
},
|
||||||
|
|
||||||
|
openTabByName: function(tabName) {
|
||||||
|
let tablinkEl = document.getElementById("tablink-" + tabName);
|
||||||
|
let tabcontentEl = document.getElementById("tabcontent-" + tabName);
|
||||||
|
if (!tablinkEl || !tabcontentEl) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tablinks = document.getElementsByClassName("tabbed-changeform-tablink");
|
||||||
|
let tabcontents = document.getElementsByClassName("tabbed-changeform-tabcontent");
|
||||||
|
|
||||||
|
// toggle tab link
|
||||||
|
for (let tablink of tablinks) {
|
||||||
|
tablink.classList.remove("active");
|
||||||
|
}
|
||||||
|
tablinkEl.classList.add("active");
|
||||||
|
|
||||||
|
// toggle tab content
|
||||||
|
for (let tabcontent of tabcontents) {
|
||||||
|
tabcontent.classList.remove("active");
|
||||||
|
}
|
||||||
|
tabcontentEl.classList.add("active");
|
||||||
|
|
||||||
|
// update location hash
|
||||||
|
let history = window.history;
|
||||||
|
if (history) {
|
||||||
|
history.replaceState(undefined, undefined, "#" + tabName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
openTabByLocationHash: function() {
|
||||||
|
let hash = window.location.hash;
|
||||||
|
if (hash && hash !== "#") {
|
||||||
|
let tabName = hash.substring(1);
|
||||||
|
if (this.openTabByName(tabName)) {
|
||||||
|
this.scrollTabsToTabByName(tabName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
scrollTabsToTabByName: function(tabName) {
|
||||||
|
let tabsEl = document.getElementById("tabbed-changeform-tabs");
|
||||||
|
let tablinkEl = document.getElementById("tablink-" + tabName);
|
||||||
|
if (!tabsEl || !tablinkEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let tablinkLeft = (tablinkEl.offsetLeft - tabsEl.offsetLeft);
|
||||||
|
let tabsScrollLeft = Math.ceil(tablinkLeft);
|
||||||
|
tabsEl.scrollTo({
|
||||||
|
top: 0,
|
||||||
|
left: tabsScrollLeft,
|
||||||
|
behavior: "instant"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// scope.tabbedChangeForm.openTabByLocationHash();
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
scope.tabbedChangeForm.openTabByLocationHash();
|
||||||
|
}, false);
|
||||||
|
|
||||||
|
}(window.AdminInterface = window.AdminInterface || {}));
|
||||||
21
backend/staticfiles/ckeditor/ckeditor/skins/light/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Ikimea
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ckeditor-light-theme
|
||||||
|
====================
|
||||||
13
backend/staticfiles/ckeditor/ckeditor/skins/light/bower.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "ckeditor-light-theme",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"homepage": "https://github.com/Ikimea/ckeditor-light-theme",
|
||||||
|
"authors": [
|
||||||
|
"Mbechezi Mlanawo <mlanawo.mbechezi@ikimea.com>"
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
"ckeditor",
|
||||||
|
"theme"
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
1348
backend/staticfiles/ckeditor/ckeditor/skins/light/editor.css
Normal file
BIN
backend/staticfiles/ckeditor/ckeditor/skins/light/icons.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 824 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 736 B |
|
After Width: | Height: | Size: 728 B |
|
After Width: | Height: | Size: 953 B |
322
backend/staticfiles/ckeditor/ckeditor/skins/light/skin.js
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
/**
|
||||||
|
* @license Copyright (c) 2003-2014, CKSource - Frederico Knabben. All rights reserved.
|
||||||
|
* For licensing, see LICENSE.md or http://ckeditor.com/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
skin.js
|
||||||
|
=========
|
||||||
|
|
||||||
|
In this file we interact with the CKEditor JavaScript API to register the skin
|
||||||
|
and enable additional skin related features.
|
||||||
|
|
||||||
|
The level of complexity of this file depends on the features available in the
|
||||||
|
skin. There is only one mandatory line of code to be included here, which is
|
||||||
|
setting CKEDITOR.skin.name. All the rest is optional, but recommended to be
|
||||||
|
implemented as they make higher quality skins.
|
||||||
|
|
||||||
|
For this skin, the following tasks are achieved in this file:
|
||||||
|
|
||||||
|
1. Register the skin.
|
||||||
|
2. Register browser specific skin files.
|
||||||
|
3. Define the "Chameleon" feature.
|
||||||
|
4. Register the skin icons, to have them used on the development version of
|
||||||
|
the skin.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 1. Register the skin
|
||||||
|
// ----------------------
|
||||||
|
// The CKEDITOR.skin.name property must be set to the skin name. This is a
|
||||||
|
// lower-cased name, which must match the skin folder name as well as the value
|
||||||
|
// used on config.skin to tell the editor to use the skin.
|
||||||
|
//
|
||||||
|
// This is the only mandatory property to be defined in this file.
|
||||||
|
CKEDITOR.skin.name = 'husky';
|
||||||
|
|
||||||
|
// 2. Register browser specific skin files
|
||||||
|
// -----------------------------------------
|
||||||
|
// (http://docs.cksource.com/CKEditor_4.x/Skin_SDK/Browser_Hacks)
|
||||||
|
//
|
||||||
|
// To help implementing browser specific "hacks" to the skin files and have it
|
||||||
|
// easy to maintain, it is possible to have dedicated files for such browsers,
|
||||||
|
// for both the main skin CSS files: editor.css and dialog.css.
|
||||||
|
//
|
||||||
|
// The browser files must be named after the main file names, appended by an
|
||||||
|
// underscore and the browser name (e.g. editor_ie.css, dialog_ie8.css).
|
||||||
|
//
|
||||||
|
// The accepted browser names must match the CKEDITOR.env properties. The most
|
||||||
|
// common names are: ie, opera, webkit and gecko. Check the documentation for
|
||||||
|
// the complete list:
|
||||||
|
// http://docs.ckeditor.com/#!/api/CKEDITOR.env
|
||||||
|
//
|
||||||
|
// Internet explorer is an exception and the browser version is also accepted
|
||||||
|
// (ie7, ie8, ie9, ie10), as well as a special name for IE in Quirks mode (iequirks).
|
||||||
|
//
|
||||||
|
// The available browser specific files must be set separately for editor.css
|
||||||
|
// and dialog.css.
|
||||||
|
CKEDITOR.skin.ua_editor = 'ie,iequirks,ie7,ie8,gecko';
|
||||||
|
CKEDITOR.skin.ua_dialog = 'ie,iequirks,ie7,ie8,opera';
|
||||||
|
|
||||||
|
// 3. Define the "Chameleon" feature
|
||||||
|
// -----------------------------------
|
||||||
|
// (http://docs.cksource.com/CKEditor_4.x/Skin_SDK/Chameleon)
|
||||||
|
//
|
||||||
|
// "Chameleon" is a unique feature available in CKEditor. It makes it possible
|
||||||
|
// to end users to specify which color to use as the basis for the editor UI.
|
||||||
|
// It is enough to set config.uiColor to any color value and voila, the UI is
|
||||||
|
// colored.
|
||||||
|
//
|
||||||
|
// The only detail here is that the skin itself must be compatible with the
|
||||||
|
// Chameleon feature. That's because the skin CSS files are the responsible to
|
||||||
|
// apply colors in the UI and each skin do that in different way and on
|
||||||
|
// different places.
|
||||||
|
//
|
||||||
|
// Implementing the Chameleon feature requires a bit of JavaScript programming.
|
||||||
|
// The CKEDITOR.skin.chameleon function must be defined. It must return the CSS
|
||||||
|
// "template" to be used to change the color of a specific CKEditor instance
|
||||||
|
// available in the page. When a color change is required, this template is
|
||||||
|
// appended to the page holding the editor, overriding styles defined in the
|
||||||
|
// skin files.
|
||||||
|
//
|
||||||
|
// The "$color" placeholder can be used in the returned string. It'll be
|
||||||
|
// replaced with the desired color.
|
||||||
|
CKEDITOR.skin.chameleon = (function() {
|
||||||
|
// This method can be used to adjust colour brightness of various element.
|
||||||
|
// Colours are accepted in 7-byte hex format, for example: #00ff00.
|
||||||
|
// Brightness ratio must be a float number within [-1, 1],
|
||||||
|
// where -1 is black, 1 is white and 0 is the original colour.
|
||||||
|
var colorBrightness = (function() {
|
||||||
|
function channelBrightness(channel, ratio) {
|
||||||
|
return ( '0' + ( ratio < 0 ?
|
||||||
|
0 | channel * ( 1 + ratio )
|
||||||
|
:
|
||||||
|
0 | channel + ( 255 - channel ) * ratio ).toString(16)
|
||||||
|
).slice(-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return function(hexColor, ratio) {
|
||||||
|
var channels = hexColor.match(/[^#]./g);
|
||||||
|
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
channels[ i ] = channelBrightness(parseInt(channels[ i ], 16), ratio);
|
||||||
|
|
||||||
|
return '#' + channels.join('');
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
|
||||||
|
// Use this function just to avoid having to repeat all these rules on
|
||||||
|
// several places of our template.
|
||||||
|
verticalGradient = (function() {
|
||||||
|
var template = new CKEDITOR.template('background:#{to};' +
|
||||||
|
'background-image:-webkit-gradient(linear,lefttop,leftbottom,from({from}),to({to}));' +
|
||||||
|
'background-image:-moz-linear-gradient(top,{from},{to});' +
|
||||||
|
'background-image:-webkit-linear-gradient(top,{from},{to});' +
|
||||||
|
'background-image:-o-linear-gradient(top,{from},{to});' +
|
||||||
|
'background-image:-ms-linear-gradient(top,{from},{to});' +
|
||||||
|
'background-image:linear-gradient(top,{from},{to});' +
|
||||||
|
'filter:progid:DXImageTransform.Microsoft.gradient(gradientType=0,startColorstr=\'{from}\',endColorstr=\'{to}\');');
|
||||||
|
|
||||||
|
return function(from, to) {
|
||||||
|
return template.output({ from: from, to: to });
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
|
||||||
|
// Style templates for various user interface parts:
|
||||||
|
// * Default editor template.
|
||||||
|
// * Default panel template.
|
||||||
|
templates = {
|
||||||
|
editor: new CKEDITOR.template(
|
||||||
|
'{id}.cke_chrome [border-color:{defaultBorder};] ' +
|
||||||
|
'{id} .cke_top [ ' +
|
||||||
|
'{defaultGradient}' +
|
||||||
|
'border-bottom-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_bottom [' +
|
||||||
|
'{defaultGradient}' +
|
||||||
|
'border-top-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_resizer [border-right-color:{ckeResizer}] ' +
|
||||||
|
|
||||||
|
// Dialogs.
|
||||||
|
'{id} .cke_dialog_title [' +
|
||||||
|
'{defaultGradient}' +
|
||||||
|
'border-bottom-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_dialog_footer [' +
|
||||||
|
'{defaultGradient}' +
|
||||||
|
'outline-color:{defaultBorder};' +
|
||||||
|
'border-top-color:{defaultBorder};' + // IE7 doesn't use outline.
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_dialog_tab [' +
|
||||||
|
'{lightGradient}' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_dialog_tab:hover [' +
|
||||||
|
'{mediumGradient}' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_dialog_contents [' +
|
||||||
|
'border-top-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_dialog_tab_selected, {id} .cke_dialog_tab_selected:hover [' +
|
||||||
|
'background:{dialogTabSelected};' +
|
||||||
|
'border-bottom-color:{dialogTabSelectedBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_dialog_body [' +
|
||||||
|
'background:{dialogBody};' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
|
||||||
|
// Toolbars, buttons.
|
||||||
|
'{id} .cke_toolgroup [' +
|
||||||
|
'{lightGradient}' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} a.cke_button_off:hover, {id} a.cke_button_off:focus, {id} a.cke_button_off:active [' +
|
||||||
|
'{mediumGradient}' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_button_on [' +
|
||||||
|
'{ckeButtonOn}' +
|
||||||
|
'] ' +
|
||||||
|
'{id} .cke_toolbar_separator [' +
|
||||||
|
'background-color: {ckeToolbarSeparator};' +
|
||||||
|
'] ' +
|
||||||
|
|
||||||
|
// Combo buttons.
|
||||||
|
'{id} .cke_combo_button [' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'{lightGradient}' +
|
||||||
|
'] ' +
|
||||||
|
'{id} a.cke_combo_button:hover, {id} a.cke_combo_button:focus, {id} .cke_combo_on a.cke_combo_button [' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'{mediumGradient}' +
|
||||||
|
'] ' +
|
||||||
|
|
||||||
|
// Elementspath.
|
||||||
|
'{id} .cke_path_item [' +
|
||||||
|
'color:{elementsPathColor};' +
|
||||||
|
'] ' +
|
||||||
|
'{id} a.cke_path_item:hover, {id} a.cke_path_item:focus, {id} a.cke_path_item:active [' +
|
||||||
|
'background-color:{elementsPathBg};' +
|
||||||
|
'] ' +
|
||||||
|
|
||||||
|
'{id}.cke_panel [' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] '
|
||||||
|
),
|
||||||
|
panel: new CKEDITOR.template(
|
||||||
|
// Panel drop-downs.
|
||||||
|
'.cke_panel_grouptitle [' +
|
||||||
|
'{lightGradient}' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
|
||||||
|
// Context menus.
|
||||||
|
'.cke_menubutton_icon [' +
|
||||||
|
'background-color:{menubuttonIcon};' +
|
||||||
|
'] ' +
|
||||||
|
'.cke_menubutton:hover .cke_menubutton_icon, .cke_menubutton:focus .cke_menubutton_icon, .cke_menubutton:active .cke_menubutton_icon [' +
|
||||||
|
'background-color:{menubuttonIconHover};' +
|
||||||
|
'] ' +
|
||||||
|
'.cke_menuseparator [' +
|
||||||
|
'background-color:{menubuttonIcon};' +
|
||||||
|
'] ' +
|
||||||
|
|
||||||
|
// Color boxes.
|
||||||
|
'a:hover.cke_colorbox, a:focus.cke_colorbox, a:active.cke_colorbox [' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] ' +
|
||||||
|
'a:hover.cke_colorauto, a:hover.cke_colormore, a:focus.cke_colorauto, a:focus.cke_colormore, a:active.cke_colorauto, a:active.cke_colormore [' +
|
||||||
|
'background-color:{ckeColorauto};' +
|
||||||
|
'border-color:{defaultBorder};' +
|
||||||
|
'] '
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
return function(editor, part) {
|
||||||
|
var uiColor = editor.uiColor,
|
||||||
|
// The following are CSS styles used in templates.
|
||||||
|
// Styles are generated according to current editor.uiColor.
|
||||||
|
templateStyles = {
|
||||||
|
// CKEditor instances have a unique ID, which is used as class name into
|
||||||
|
// the outer container of the editor UI (e.g. ".cke_1").
|
||||||
|
//
|
||||||
|
// The Chameleon feature is available for each CKEditor instance,
|
||||||
|
// independently. Because of this, we need to prefix all CSS selectors with
|
||||||
|
// the unique class name of the instance.
|
||||||
|
id: '.' + editor.id,
|
||||||
|
|
||||||
|
// These styles are used by various UI elements.
|
||||||
|
defaultBorder: colorBrightness(uiColor, -0.1),
|
||||||
|
defaultGradient: verticalGradient(colorBrightness(uiColor, 0.9), uiColor),
|
||||||
|
lightGradient: verticalGradient(colorBrightness(uiColor, 1), colorBrightness(uiColor, 0.7)),
|
||||||
|
mediumGradient: verticalGradient(colorBrightness(uiColor, 0.8), colorBrightness(uiColor, 0.5)),
|
||||||
|
|
||||||
|
// These are for specific UI elements.
|
||||||
|
ckeButtonOn: verticalGradient(colorBrightness(uiColor, 0.6), colorBrightness(uiColor, 0.7)),
|
||||||
|
ckeResizer: colorBrightness(uiColor, -0.4),
|
||||||
|
ckeToolbarSeparator: colorBrightness(uiColor, 0.5),
|
||||||
|
ckeColorauto: colorBrightness(uiColor, 0.8),
|
||||||
|
dialogBody: colorBrightness(uiColor, 0.7),
|
||||||
|
// Use gradient instead of simple hex to avoid further filter resetting in IE.
|
||||||
|
dialogTabSelected: verticalGradient('#FFFFFF', '#FFFFFF'),
|
||||||
|
dialogTabSelectedBorder: '#FFF',
|
||||||
|
elementsPathColor: colorBrightness(uiColor, -0.6),
|
||||||
|
elementsPathBg: uiColor,
|
||||||
|
menubuttonIcon: colorBrightness(uiColor, 0.5),
|
||||||
|
menubuttonIconHover: colorBrightness(uiColor, 0.3)
|
||||||
|
};
|
||||||
|
|
||||||
|
return templates[ part ]
|
||||||
|
.output(templateStyles)
|
||||||
|
.replace(/\[/g, '{') // Replace brackets with braces.
|
||||||
|
.replace(/\]/g, '}');
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
|
// %REMOVE_START%
|
||||||
|
|
||||||
|
// 4. Register the skin icons for development purposes only
|
||||||
|
// ----------------------------------------------------------
|
||||||
|
// (http://docs.cksource.com/CKEditor_4.x/Skin_SDK/Icons)
|
||||||
|
//
|
||||||
|
// Note: As "moono" is the default CKEditor skin, it provides no custom icons,
|
||||||
|
// thus this code is commented out.
|
||||||
|
//
|
||||||
|
// This code is here just to make the skin work fully when using its "source"
|
||||||
|
// version. Without this, the skin will still work, but its icons will not be
|
||||||
|
// used (again, on source version only).
|
||||||
|
//
|
||||||
|
// This block of code is not necessary on the release version of the skin.
|
||||||
|
// Because of this it is very important to include it inside the REMOVE_START
|
||||||
|
// and REMOVE_END comment markers, so the skin builder will properly clean
|
||||||
|
// things up.
|
||||||
|
//
|
||||||
|
// If a required icon is not available here, the plugin defined icon will be
|
||||||
|
// used instead. This means that a skin is not required to provide all icons.
|
||||||
|
// Actually, it is not required to provide icons at all.
|
||||||
|
//
|
||||||
|
// (function() {
|
||||||
|
// // The available icons. This list must match the file names (without
|
||||||
|
// // extension) available inside the "icons" folder.
|
||||||
|
// var icons = ( 'about,anchor-rtl,anchor,bgcolor,bidiltr,bidirtl,blockquote,' +
|
||||||
|
// 'bold,bulletedlist-rtl,bulletedlist,button,checkbox,copy-rtl,copy,' +
|
||||||
|
// 'creatediv,cut-rtl,cut,docprops-rtl,docprops,find-rtl,find,flash,form,' +
|
||||||
|
// 'hiddenfield,horizontalrule,icons,iframe,image,imagebutton,indent-rtl,' +
|
||||||
|
// 'indent,italic,justifyblock,justifycenter,justifyleft,justifyright,' +
|
||||||
|
// 'link,maximize,newpage-rtl,newpage,numberedlist-rtl,numberedlist,' +
|
||||||
|
// 'outdent-rtl,outdent,pagebreak-rtl,pagebreak,paste-rtl,paste,' +
|
||||||
|
// 'pastefromword-rtl,pastefromword,pastetext-rtl,pastetext,preview-rtl,' +
|
||||||
|
// 'preview,print,radio,redo-rtl,redo,removeformat,replace,save,scayt,' +
|
||||||
|
// 'select-rtl,select,selectall,showblocks-rtl,showblocks,smiley,' +
|
||||||
|
// 'source-rtl,source,specialchar,spellchecker,strike,subscript,' +
|
||||||
|
// 'superscript,table,templates-rtl,templates,textarea-rtl,textarea,' +
|
||||||
|
// 'textcolor,textfield-rtl,textfield,uicolor,underline,undo-rtl,undo,unlink' ).split( ',' );
|
||||||
|
//
|
||||||
|
// var iconsFolder = CKEDITOR.getUrl( CKEDITOR.skin.path() + 'icons/' + ( CKEDITOR.env.hidpi ? 'hidpi/' : '' ) );
|
||||||
|
//
|
||||||
|
// for ( var i = 0; i < icons.length; i++ ) {
|
||||||
|
// CKEDITOR.skin.addIcon( icons[ i ], iconsFolder + icons[ i ] + '.png' );
|
||||||
|
// }
|
||||||
|
// })();
|
||||||
|
|
||||||
|
// %REMOVE_END%
|
||||||
11
backend/staticfiles/colorfield/colorfield.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
window.addEventListener('load', function () {
|
||||||
|
const inputs = document.getElementsByClassName('colorfield_field coloris');
|
||||||
|
for (const input of inputs) {
|
||||||
|
const colorisId = input.getAttribute('data-coloris-options-json-script-id');
|
||||||
|
const script = document.querySelector(`script[id='${colorisId}']`);
|
||||||
|
const options = JSON.parse(script.textContent);
|
||||||
|
|
||||||
|
const id = input.getAttribute('id');
|
||||||
|
Coloris.setInstance(`.colorfield_field.coloris.${id}`, options);
|
||||||
|
}
|
||||||
|
});
|
||||||
3
backend/staticfiles/colorfield/coloris/README.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
https://github.com/mdbassit/Coloris
|
||||||
|
|
||||||
|
Release: v0.24.0
|
||||||
577
backend/staticfiles/colorfield/coloris/coloris.css
Normal file
@@ -0,0 +1,577 @@
|
|||||||
|
.clr-picker {
|
||||||
|
display: none;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
position: absolute;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 1000;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #fff;
|
||||||
|
justify-content: flex-end;
|
||||||
|
direction: ltr;
|
||||||
|
box-shadow: 0 0 5px rgba(0,0,0,.05), 0 5px 20px rgba(0,0,0,.1);
|
||||||
|
-moz-user-select: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker.clr-open,
|
||||||
|
.clr-picker[data-inline="true"] {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker[data-inline="true"] {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-gradient {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
background-image: linear-gradient(rgba(0,0,0,0), #000), linear-gradient(90deg, #fff, currentColor);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-marker {
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
margin: -6px 0 0 -6px;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: currentColor;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker input[type="range"]::-webkit-slider-runnable-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker input[type="range"]::-webkit-slider-thumb {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker input[type="range"]::-moz-range-track {
|
||||||
|
width: 100%;
|
||||||
|
height: 16px;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker input[type="range"]::-moz-range-thumb {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-hue {
|
||||||
|
background-image: linear-gradient(to right, #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%, #00f 66.66%, #f0f 83.33%, #f00 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-hue,
|
||||||
|
.clr-alpha {
|
||||||
|
position: relative;
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
height: 8px;
|
||||||
|
margin: 5px 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-alpha span {
|
||||||
|
display: block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
border-radius: inherit;
|
||||||
|
background-image: linear-gradient(90deg, rgba(0,0,0,0), currentColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-hue input[type="range"],
|
||||||
|
.clr-alpha input[type="range"] {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(100% + 32px);
|
||||||
|
height: 16px;
|
||||||
|
left: -16px;
|
||||||
|
top: -4px;
|
||||||
|
margin: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-hue div,
|
||||||
|
.clr-alpha div {
|
||||||
|
position: absolute;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
left: 0;
|
||||||
|
top: 50%;
|
||||||
|
margin-left: -8px;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
border: 2px solid #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: currentColor;
|
||||||
|
box-shadow: 0 0 1px #888;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-alpha div:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-format {
|
||||||
|
display: none;
|
||||||
|
order: 1;
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
margin: 0 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-segmented {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-segmented input,
|
||||||
|
.clr-segmented legend {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-segmented label {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
padding: 4px 0;
|
||||||
|
font-size: inherit;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: initial;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-segmented label:first-of-type {
|
||||||
|
border-radius: 10px 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-segmented label:last-of-type {
|
||||||
|
border-radius: 0 10px 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-segmented input:checked + label {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-swatches {
|
||||||
|
order: 2;
|
||||||
|
width: calc(100% - 32px);
|
||||||
|
margin: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-swatches div {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-swatches button {
|
||||||
|
position: relative;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 0 4px 6px 4px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: inherit;
|
||||||
|
text-indent: -1000px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-swatches button:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
background-color: currentColor;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.clr-color {
|
||||||
|
order: 1;
|
||||||
|
width: calc(100% - 80px);
|
||||||
|
height: 32px;
|
||||||
|
margin: 15px 20px 20px auto;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 16px;
|
||||||
|
color: #444;
|
||||||
|
background-color: #fff;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.clr-color:focus {
|
||||||
|
outline: none;
|
||||||
|
border: 1px solid #1e90ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-close,
|
||||||
|
.clr-clear {
|
||||||
|
display: none;
|
||||||
|
order: 2;
|
||||||
|
height: 24px;
|
||||||
|
margin: 0 20px 20px;
|
||||||
|
padding: 0 20px;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 12px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #666;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-close {
|
||||||
|
display: block;
|
||||||
|
margin: 0 20px 20px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-preview {
|
||||||
|
position: relative;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin: 15px 0 20px 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-preview:before,
|
||||||
|
.clr-preview:after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-preview:after {
|
||||||
|
border: 0;
|
||||||
|
background-color: currentColor;
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-preview button {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 1;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
outline-offset: -2px;
|
||||||
|
background-color: transparent;
|
||||||
|
text-indent: -9999px;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-marker,
|
||||||
|
.clr-hue div,
|
||||||
|
.clr-alpha div,
|
||||||
|
.clr-color {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-field {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-field input {
|
||||||
|
margin: 0;
|
||||||
|
direction: ltr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-field.clr-rtl input {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-field button {
|
||||||
|
position: absolute;
|
||||||
|
width: 30px;
|
||||||
|
height: 100%;
|
||||||
|
right: 0;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
color: inherit;
|
||||||
|
text-indent: -1000px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-field.clr-rtl button {
|
||||||
|
right: auto;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-field button:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
border-radius: inherit;
|
||||||
|
background-color: currentColor;
|
||||||
|
box-shadow: inset 0 0 1px rgba(0,0,0,.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-alpha,
|
||||||
|
.clr-alpha div,
|
||||||
|
.clr-swatches button,
|
||||||
|
.clr-preview:before,
|
||||||
|
.clr-field button {
|
||||||
|
background-image: repeating-linear-gradient(45deg, #aaa 25%, transparent 25%, transparent 75%, #aaa 75%, #aaa), repeating-linear-gradient(45deg, #aaa 25%, #fff 25%, #fff 75%, #aaa 75%, #aaa);
|
||||||
|
background-position: 0 0, 4px 4px;
|
||||||
|
background-size: 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-marker:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-keyboard-nav .clr-marker:focus,
|
||||||
|
.clr-keyboard-nav .clr-hue input:focus + div,
|
||||||
|
.clr-keyboard-nav .clr-alpha input:focus + div,
|
||||||
|
.clr-keyboard-nav .clr-segmented input:focus + label {
|
||||||
|
outline: none;
|
||||||
|
box-shadow: 0 0 0 2px #1e90ff, 0 0 2px 2px #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker[data-alpha="false"] .clr-alpha {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker[data-minimal="true"] {
|
||||||
|
padding-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker[data-minimal="true"] .clr-gradient,
|
||||||
|
.clr-picker[data-minimal="true"] .clr-hue,
|
||||||
|
.clr-picker[data-minimal="true"] .clr-alpha,
|
||||||
|
.clr-picker[data-minimal="true"] .clr-color,
|
||||||
|
.clr-picker[data-minimal="true"] .clr-preview {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dark theme **/
|
||||||
|
|
||||||
|
.clr-dark {
|
||||||
|
background-color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-dark .clr-segmented {
|
||||||
|
border-color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-dark .clr-swatches button:after {
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(255,255,255,.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-dark input.clr-color {
|
||||||
|
color: #fff;
|
||||||
|
border-color: #777;
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-dark input.clr-color:focus {
|
||||||
|
border-color: #1e90ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-dark .clr-preview:after {
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-dark .clr-alpha,
|
||||||
|
.clr-dark .clr-alpha div,
|
||||||
|
.clr-dark .clr-swatches button,
|
||||||
|
.clr-dark .clr-preview:before {
|
||||||
|
background-image: repeating-linear-gradient(45deg, #666 25%, transparent 25%, transparent 75%, #888 75%, #888), repeating-linear-gradient(45deg, #888 25%, #444 25%, #444 75%, #888 75%, #888);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Polaroid theme **/
|
||||||
|
|
||||||
|
.clr-picker.clr-polaroid {
|
||||||
|
border-radius: 6px;
|
||||||
|
box-shadow: 0 0 5px rgba(0,0,0,.1), 0 5px 30px rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker.clr-polaroid:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
width: 16px;
|
||||||
|
height: 10px;
|
||||||
|
left: 20px;
|
||||||
|
top: -10px;
|
||||||
|
border: solid transparent;
|
||||||
|
border-width: 0 8px 10px 8px;
|
||||||
|
border-bottom-color: currentColor;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #fff;
|
||||||
|
filter: drop-shadow(0 -4px 3px rgba(0,0,0,.1));
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker.clr-polaroid.clr-dark:before {
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker.clr-polaroid.clr-left:before {
|
||||||
|
left: auto;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-picker.clr-polaroid.clr-top:before {
|
||||||
|
top: auto;
|
||||||
|
bottom: -10px;
|
||||||
|
transform: rotateZ(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-gradient {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
height: 120px;
|
||||||
|
margin: 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-hue,
|
||||||
|
.clr-polaroid .clr-alpha {
|
||||||
|
width: calc(100% - 30px);
|
||||||
|
height: 10px;
|
||||||
|
margin: 6px 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-hue div,
|
||||||
|
.clr-polaroid .clr-alpha div {
|
||||||
|
box-shadow: 0 0 5px rgba(0,0,0,.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-format {
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
margin: 0 10px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-swatches {
|
||||||
|
width: calc(100% - 12px);
|
||||||
|
margin: 0 6px;
|
||||||
|
}
|
||||||
|
.clr-polaroid .clr-swatches div {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-swatches button {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid input.clr-color {
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
margin: 10px 10px 15px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-clear {
|
||||||
|
margin: 0 10px 15px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-close {
|
||||||
|
margin: 0 10px 15px auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-polaroid .clr-preview {
|
||||||
|
margin: 10px 0 15px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Large theme **/
|
||||||
|
|
||||||
|
.clr-picker.clr-large {
|
||||||
|
width: 275px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-large .clr-gradient {
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-large .clr-swatches button {
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pill (horizontal) theme **/
|
||||||
|
|
||||||
|
.clr-picker.clr-pill {
|
||||||
|
width: 380px;
|
||||||
|
padding-left: 180px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-pill .clr-gradient {
|
||||||
|
position: absolute;
|
||||||
|
width: 180px;
|
||||||
|
height: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-radius: 3px 0 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clr-pill .clr-hue {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
1263
backend/staticfiles/colorfield/coloris/coloris.js
Normal file
1
backend/staticfiles/colorfield/coloris/coloris.min.css
vendored
Normal file
6
backend/staticfiles/colorfield/coloris/coloris.min.js
vendored
Normal file
22
backend/staticfiles/import_export/action_formats.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
(function($) {
|
||||||
|
$(document).ready(function() {
|
||||||
|
var $actionsSelect, $formatsElement;
|
||||||
|
if ($('body').hasClass('grp-change-list')) {
|
||||||
|
// using grappelli
|
||||||
|
$actionsSelect = $('#grp-changelist-form select[name="action"]');
|
||||||
|
$formatsElement = $('#grp-changelist-form select[name="file_format"]');
|
||||||
|
} else {
|
||||||
|
// using default admin
|
||||||
|
$actionsSelect = $('#changelist-form select[name="action"]');
|
||||||
|
$formatsElement = $('#changelist-form select[name="file_format"]').parent();
|
||||||
|
}
|
||||||
|
$actionsSelect.change(function() {
|
||||||
|
if ($(this).val() === 'export_admin_action') {
|
||||||
|
$formatsElement.show();
|
||||||
|
} else {
|
||||||
|
$formatsElement.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$actionsSelect.change();
|
||||||
|
});
|
||||||
|
})(django.jQuery);
|
||||||
21
backend/staticfiles/import_export/guess_format.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
(function($) {
|
||||||
|
$().ready(function () {
|
||||||
|
$('input.guess_format[type="file"]').change(function () {
|
||||||
|
var files = this.files;
|
||||||
|
var dropdowns = $(this.form).find('select.guess_format');
|
||||||
|
if(files.length > 0) {
|
||||||
|
var extension = files[0].name.split('.').pop().trim().toLowerCase();
|
||||||
|
for(var i = 0; i < dropdowns.length; i++) {
|
||||||
|
var dropdown = dropdowns[i];
|
||||||
|
dropdown.selectedIndex = 0;
|
||||||
|
for(var j = 0; j < dropdown.options.length; j++) {
|
||||||
|
if(extension === dropdown.options[j].text.trim().toLowerCase()) {
|
||||||
|
dropdown.selectedIndex = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})(django.jQuery);
|
||||||
115
backend/staticfiles/import_export/import.css
vendored
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
.import-preview .errors {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-count {
|
||||||
|
display: inline-block;
|
||||||
|
background-color: #e40000;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: white;
|
||||||
|
font-size: 0.9em;
|
||||||
|
position: relative;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: -2px;
|
||||||
|
padding: 0.2em 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-container {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
background-color: #ffc1c1;
|
||||||
|
padding: 14px 15px 10px;
|
||||||
|
top: 25px;
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
width: 200px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.skip {
|
||||||
|
background-color: #d2d2d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.new {
|
||||||
|
background-color: #bdd8b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.delete {
|
||||||
|
background-color: #f9bebf;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.update {
|
||||||
|
background-color: #fdfdcf;
|
||||||
|
}
|
||||||
|
|
||||||
|
.import-preview td:hover .validation-error-count {
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.import-preview td:hover .validation-error-container {
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-list {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-list li {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-list > li > ul {
|
||||||
|
margin: 8px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-list > li > ul > li {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
line-height: 1.28em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-field-label {
|
||||||
|
display: block;
|
||||||
|
border-bottom: 1px solid #e40000;
|
||||||
|
color: #e40000;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
table.import-preview tr.skip {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.new {
|
||||||
|
background-color: #42274d;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.delete {
|
||||||
|
background-color: #064140;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview tr.update {
|
||||||
|
background-color: #020230;
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error-container {
|
||||||
|
background-color: #003e3e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
these declarations are necessary to forcibly override the
|
||||||
|
formatting applied by the diff-match-patch python library
|
||||||
|
*/
|
||||||
|
table.import-preview td ins {
|
||||||
|
background-color: #190019 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.import-preview td del {
|
||||||
|
background-color: #001919 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
25
backend/staticfiles/rangefilter/iife.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
django.jQuery(".admindatefilter").each(
|
||||||
|
function(){
|
||||||
|
var form_id = django.jQuery(this).find("form").attr('id').slice(0,-5);
|
||||||
|
var qs_name = form_id+"-query-string";
|
||||||
|
var query_string = django.jQuery('input#'+qs_name).val();
|
||||||
|
var form_name = form_id+"-form";
|
||||||
|
|
||||||
|
// Bind submit buttons
|
||||||
|
django.jQuery(this).find("input[type=select]").bind("click",
|
||||||
|
function(event){
|
||||||
|
event.preventDefault();
|
||||||
|
var form_data = django.jQuery('#'+form_name).serialize();
|
||||||
|
amp = query_string == "?" ? "" : "&"; // avoid leading ?& combination
|
||||||
|
window.location = window.location.pathname + query_string + amp + form_data;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bind reset buttons
|
||||||
|
django.jQuery(this).find("input[type=reset]").bind("click",
|
||||||
|
function(){
|
||||||
|
window.location = window.location.pathname + query_string;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
22
backend/staticfiles/streamfield/js/admin_popup_response.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
(function() {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var windowRef = window;
|
||||||
|
var openerRef = windowRef.parent;
|
||||||
|
|
||||||
|
var initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
|
||||||
|
switch (initData.action) {
|
||||||
|
case 'change':
|
||||||
|
openerRef.streamapps[initData.app_id].updateBlock(initData.block_id, initData.instance_id);
|
||||||
|
openerRef.dismissRelatedObjectModal();
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
openerRef.streamapps[initData.app_id].updateBlock(initData.block_id, initData.instance_id);
|
||||||
|
openerRef.dismissRelatedObjectModal();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||