mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-03-03 18:48:23 +00:00
Merge branch 'master' of PyAssets into assets
This commit is contained in:
0
assets/__init__.py
Normal file
0
assets/__init__.py
Normal file
42
assets/admin.py
Normal file
42
assets/admin.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from django.contrib import admin
|
||||
from assets import models as assets
|
||||
|
||||
|
||||
@admin.register(assets.AssetCategory)
|
||||
class AssetCategoryAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'name']
|
||||
ordering = ['id']
|
||||
|
||||
|
||||
@admin.register(assets.AssetStatus)
|
||||
class AssetStatusAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'name']
|
||||
ordering = ['id']
|
||||
|
||||
|
||||
@admin.register(assets.Supplier)
|
||||
class SupplierAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'name']
|
||||
ordering = ['id']
|
||||
|
||||
|
||||
@admin.register(assets.Asset)
|
||||
class AssetAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', 'asset_id', 'description', 'category', 'status']
|
||||
list_filter = ['is_cable', 'category']
|
||||
search_fields = ['id', 'asset_id', 'description']
|
||||
|
||||
|
||||
@admin.register(assets.Connector)
|
||||
class ConnectorAdmin(admin.ModelAdmin):
|
||||
list_display = ['id', '__str__', 'current_rating', 'voltage_rating', 'num_pins']
|
||||
|
||||
|
||||
@admin.register(assets.Cable)
|
||||
class CableAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
|
||||
admin.AdminSite.site_header = 'PyAssets - TEC\'s Asset System'
|
||||
admin.AdminSite.site_title = 'PyAssets Admin'
|
||||
admin.AdminSite.index_title = 'System Administration'
|
||||
29
assets/api.py
Normal file
29
assets/api.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# endpoint method result
|
||||
#
|
||||
# api/assets/ get list all assets
|
||||
# api/assets/<id> get get a specific asset
|
||||
|
||||
|
||||
from rest_framework import serializers, viewsets, status
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.generics import get_object_or_404
|
||||
from django.db.models import Min
|
||||
from django.core.mail import EmailMessage
|
||||
from django.template.loader import get_template
|
||||
from django.template import Context, RequestContext
|
||||
import datetime
|
||||
|
||||
from assets import models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class AssetSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = models.Asset
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class AssetViewSet(viewsets.ModelViewSet):
|
||||
queryset = models.Asset.objects.all()
|
||||
serializer_class = AssetSerializer
|
||||
5
assets/apps.py
Normal file
5
assets/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class AssetsConfig(AppConfig):
|
||||
name = 'assets'
|
||||
9
assets/filters.py
Normal file
9
assets/filters.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import django_filters
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
class AssetFilter(django_filters.FilterSet):
|
||||
class Meta:
|
||||
model = models.Asset
|
||||
fields = ['asset_id', 'description', 'category', 'status']
|
||||
15
assets/forms.py
Normal file
15
assets/forms.py
Normal file
@@ -0,0 +1,15 @@
|
||||
from django import forms
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
class AssetForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = models.Asset
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class SupplierForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = models.Supplier
|
||||
fields = '__all__'
|
||||
0
assets/management/__init__.py
Normal file
0
assets/management/__init__.py
Normal file
0
assets/management/commands/__init__.py
Normal file
0
assets/management/commands/__init__.py
Normal file
27
assets/management/commands/createBaseUsers.py
Normal file
27
assets/management/commands/createBaseUsers.py
Normal file
@@ -0,0 +1,27 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Creates a super user'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
if not (settings.DEBUG or settings.STAGING):
|
||||
raise CommandError('You cannot run this command in production')
|
||||
|
||||
self.create_user_object('super', True, True)
|
||||
self.create_user_object('staff', True)
|
||||
self.create_user_object('basic')
|
||||
|
||||
@staticmethod
|
||||
def create_user_object(name, staff=False, superuser=False):
|
||||
user, created = User.objects.get_or_create(
|
||||
username=name, defaults={'email': '{}@{}.com'.format(name, name),
|
||||
'first_name': name.title(), 'last_name': 'User', 'is_superuser': superuser,
|
||||
'is_staff': staff})
|
||||
|
||||
if created:
|
||||
user.set_password(name)
|
||||
user.save()
|
||||
64
assets/management/commands/createSampleData.py
Normal file
64
assets/management/commands/createSampleData.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.core.management import call_command
|
||||
from django.utils import timezone
|
||||
import random
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Creates some sample data for testing'
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
from django.conf import settings
|
||||
|
||||
if not settings.DEBUG:
|
||||
raise CommandError('You cannot run this command in production')
|
||||
|
||||
random.seed('Some object to see the random number generator')
|
||||
|
||||
call_command('createBaseUsers')
|
||||
|
||||
self.create_categories()
|
||||
self.create_statuses()
|
||||
self.create_suppliers()
|
||||
self.create_assets()
|
||||
|
||||
def create_categories(self):
|
||||
categories = ['Case', 'Video', 'General', 'Sound', 'Lighting', 'Rigging']
|
||||
|
||||
for cat in categories:
|
||||
models.AssetCategory.objects.create(name=cat)
|
||||
|
||||
def create_statuses(self):
|
||||
statuses = ['In Service', 'Lost', 'Binned', 'Sold', 'Broken']
|
||||
|
||||
for stat in statuses:
|
||||
models.AssetStatus.objects.create(name=stat)
|
||||
|
||||
def create_suppliers(self):
|
||||
suppliers = ["Acme, inc.","Widget Corp","123 Warehousing","Demo Company","Smith and Co.","Foo Bars","ABC Telecom","Fake Brothers","QWERTY Logistics","Demo, inc.","Sample Company","Sample, inc","Acme Corp","Allied Biscuit","Ankh-Sto Associates","Extensive Enterprise","Galaxy Corp","Globo-Chem","Mr. Sparkle","Globex Corporation","LexCorp","LuthorCorp","North Central Positronics","Omni Consimer Products","Praxis Corporation","Sombra Corporation","Sto Plains Holdings","Tessier-Ashpool","Wayne Enterprises","Wentworth Industries","ZiffCorp","Bluth Company","Strickland Propane","Thatherton Fuels","Three Waters","Water and Power","Western Gas & Electric","Mammoth Pictures","Mooby Corp","Gringotts","Thrift Bank","Flowers By Irene","The Legitimate Businessmens Club","Osato Chemicals","Transworld Consortium","Universal Export","United Fried Chicken","Virtucon","Kumatsu Motors","Keedsler Motors","Powell Motors","Industrial Automation","Sirius Cybernetics Corporation","U.S. Robotics and Mechanical Men","Colonial Movers","Corellian Engineering Corporation","Incom Corporation","General Products","Leeding Engines Ltd.","Blammo","Input, Inc.","Mainway Toys","Videlectrix","Zevo Toys","Ajax","Axis Chemical Co.","Barrytron","Carrys Candles","Cogswell Cogs","Spacely Sprockets","General Forge and Foundry","Duff Brewing Company","Dunder Mifflin","General Services Corporation","Monarch Playing Card Co.","Krustyco","Initech","Roboto Industries","Primatech","Sonky Rubber Goods","St. Anky Beer","Stay Puft Corporation","Vandelay Industries","Wernham Hogg","Gadgetron","Burleigh and Stronginthearm","BLAND Corporation","Nordyne Defense Dynamics","Petrox Oil Company","Roxxon","McMahon and Tate","Sixty Second Avenue","Charles Townsend Agency","Spade and Archer","Megadodo Publications","Rouster and Sideways","C.H. Lavatory and Sons","Globo Gym American Corp","The New Firm","SpringShield","Compuglobalhypermeganet","Data Systems","Gizmonic Institute","Initrode","Taggart Transcontinental","Atlantic Northern","Niagular","Plow King","Big Kahuna Burger","Big T Burgers and Fries","Chez Quis","Chotchkies","The Frying Dutchman","Klimpys","The Krusty Krab","Monks Diner","Milliways","Minuteman Cafe","Taco Grande","Tip Top Cafe","Moes Tavern","Central Perk","Chasers"]
|
||||
|
||||
for supplier in suppliers:
|
||||
models.Supplier.objects.create(name=supplier)
|
||||
|
||||
def create_assets(self):
|
||||
assest_description = ['Large cable', 'Shiny thing', 'New lights', 'Really expensive microphone', 'Box of fuse flaps', 'Expensive tool we didn\'t agree to buy', 'Cable drums', 'Boring amount of tape', 'Video stuff no one knows how to use', 'More amplifiers', 'Heatshrink']
|
||||
|
||||
categories = models.AssetCategory.objects.all()
|
||||
statuses = models.AssetStatus.objects.all()
|
||||
suppliers = models.Supplier.objects.all()
|
||||
|
||||
for i in range(100):
|
||||
asset = models.Asset.objects.create(
|
||||
asset_id='{}'.format(i),
|
||||
description=random.choice(assest_description),
|
||||
category=random.choice(categories),
|
||||
status=random.choice(statuses),
|
||||
date_acquired=timezone.now().date(),
|
||||
)
|
||||
|
||||
if i % 3 == 0:
|
||||
asset.purchased_from = random.choice(suppliers)
|
||||
|
||||
asset.save()
|
||||
29
assets/management/commands/deleteSampleData.py
Normal file
29
assets/management/commands/deleteSampleData.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Deletes testing sample data'
|
||||
|
||||
def handle(self, *args, **kwargs):
|
||||
from django.conf import settings
|
||||
|
||||
if not (settings.DEBUG):
|
||||
raise CommandError('You cannot run this command in production')
|
||||
|
||||
# self.delete_categories()
|
||||
# self.create_statuses()
|
||||
# self.create_suppliers()
|
||||
# self.create_collections()
|
||||
# self.create_assets()
|
||||
|
||||
self.delete_objects(models.AssetCategory)
|
||||
self.delete_objects(models.AssetStatus)
|
||||
self.delete_objects(models.Supplier)
|
||||
self.delete_objects(models.Collection)
|
||||
self.delete_objects(models.Asset)
|
||||
|
||||
def delete_objects(self, model):
|
||||
for object in model.objects.all():
|
||||
object.delete()
|
||||
229
assets/management/commands/import_old_db.py
Normal file
229
assets/management/commands/import_old_db.py
Normal file
@@ -0,0 +1,229 @@
|
||||
import os
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.conf import settings
|
||||
import datetime
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Imports old db from XML dump'
|
||||
|
||||
epoch = datetime.date(1970, 1, 1)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.import_categories()
|
||||
self.import_statuses()
|
||||
self.import_suppliers()
|
||||
self.import_collections()
|
||||
self.import_assets()
|
||||
self.import_cables()
|
||||
|
||||
@staticmethod
|
||||
def xml_path(file):
|
||||
return os.path.join(settings.BASE_DIR, 'data/DB_Dump/{}'.format(file))
|
||||
|
||||
@staticmethod
|
||||
def parse_xml(file):
|
||||
tree = ET.parse(file)
|
||||
|
||||
return tree.getroot()
|
||||
|
||||
def import_categories(self):
|
||||
# 0: updated, 1: created
|
||||
tally = [0, 0]
|
||||
root = self.parse_xml(self.xml_path('TEC_Asset_Categories.xml'))
|
||||
|
||||
for child in root:
|
||||
obj, created = models.AssetCategory.objects.update_or_create(
|
||||
pk=int(child.find('AssetCategoryID').text),
|
||||
name=child.find('AssetCategory').text
|
||||
)
|
||||
|
||||
if created:
|
||||
tally[1] += 1
|
||||
else:
|
||||
tally[0] += 1
|
||||
|
||||
print('Categories - Updated: {}, Created: {}'.format(tally[0], tally[1]))
|
||||
|
||||
def import_statuses(self):
|
||||
# 0: updated, 1: created
|
||||
tally = [0, 0]
|
||||
root = self.parse_xml(self.xml_path('TEC_Asset_Status_new.xml'))
|
||||
|
||||
for child in root:
|
||||
obj, created = models.AssetStatus.objects.update_or_create(
|
||||
pk=int(child.find('StatusID').text),
|
||||
name=child.find('Status').text
|
||||
)
|
||||
|
||||
if created:
|
||||
tally[1] += 1
|
||||
else:
|
||||
tally[0] += 1
|
||||
|
||||
print('Statuses - Updated: {}, Created: {}'.format(tally[0], tally[1]))
|
||||
|
||||
def import_suppliers(self):
|
||||
# 0: updated, 1: created
|
||||
tally = [0, 0]
|
||||
root = self.parse_xml(self.xml_path('TEC_Asset_Suppliers_new.xml'))
|
||||
|
||||
for child in root:
|
||||
obj, created = models.Supplier.objects.update_or_create(
|
||||
pk=int(child.find('Supplier_x0020_Id').text),
|
||||
name=child.find('Supplier_x0020_Name').text
|
||||
)
|
||||
|
||||
if created:
|
||||
tally[1] += 1
|
||||
else:
|
||||
tally[0] += 1
|
||||
|
||||
print('Suppliers - Updated: {}, Created: {}'.format(tally[0], tally[1]))
|
||||
|
||||
def import_assets(self):
|
||||
# 0: updated, 1: created
|
||||
tally = [0, 0]
|
||||
root = self.parse_xml(self.xml_path('TEC_Assets.xml'))
|
||||
|
||||
for child in root:
|
||||
defaults = dict()
|
||||
|
||||
# defaults['pk'] = int(child.find('ID').text)
|
||||
defaults['asset_id'] = child.find('AssetID').text
|
||||
|
||||
try:
|
||||
defaults['description'] = child.find('AssetDescription').text
|
||||
except AttributeError:
|
||||
defaults['description'] = 'None'
|
||||
|
||||
defaults['category'] = models.AssetCategory.objects.get(pk=int(child.find('AssetCategoryID').text))
|
||||
defaults['status'] = models.AssetStatus.objects.get(pk=int(child.find('StatusID').text))
|
||||
|
||||
try:
|
||||
defaults['serial_number'] = child.find('SerialNumber').text
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
defaults['purchased_from'] = models.Supplier.objects.get(pk=int(child.find('Supplier_x0020_Id').text))
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
defaults['date_acquired'] = datetime.datetime.strptime(child.find('DateAcquired').text, '%d/%m/%Y').date()
|
||||
except AttributeError:
|
||||
defaults['date_acquired'] = self.epoch
|
||||
|
||||
try:
|
||||
defaults['date_sold'] = datetime.datetime.strptime(child.find('DateSold').text, '%d/%m/%Y').date()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
defaults['purchase_price'] = float(child.find('Replacement_x0020_Value').text)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
defaults['salvage_value'] = float(child.find('SalvageValue').text)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
defaults['comments'] = child.find('Comments').text
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
date = child.find('NextSchedMaint').text.split('T')[0]
|
||||
defaults['next_sched_maint'] = datetime.datetime.strptime(date, '%Y-%m-%d').date()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
print(defaults)
|
||||
|
||||
obj, created = models.Asset.objects.update_or_create(**defaults)
|
||||
|
||||
if created:
|
||||
tally[1] += 1
|
||||
else:
|
||||
tally[0] += 1
|
||||
|
||||
print('Assets - Updated: {}, Created: {}'.format(tally[0], tally[1]))
|
||||
|
||||
def import_collections(self):
|
||||
tally = [0, 0]
|
||||
root = self.parse_xml(self.xml_path('TEC_Cable_Collections.xml'))
|
||||
|
||||
for child in root:
|
||||
defaults = dict()
|
||||
|
||||
defaults['pk'] = int(child.find('ID').text)
|
||||
defaults['name'] = child.find('Cable_x0020_Trunk').text
|
||||
|
||||
obj, created = models.Collection.objects.update_or_create(**defaults)
|
||||
|
||||
if created:
|
||||
tally[1] += 1
|
||||
else:
|
||||
tally[0] += 1
|
||||
|
||||
print('Collections - Updated: {}, Created: {}'.format(tally[0], tally[1]))
|
||||
|
||||
def import_cables(self):
|
||||
tally = [0, 0]
|
||||
root = self.parse_xml(self.xml_path('TEC_Cables.xml'))
|
||||
|
||||
for child in root:
|
||||
defaults = dict()
|
||||
|
||||
defaults['asset_id'] = child.find('Asset_x0020_Number').text
|
||||
|
||||
try:
|
||||
defaults['description'] = child.find('Type_x0020_of_x0020_Cable').text
|
||||
except AttributeError:
|
||||
defaults['description'] = 'None'
|
||||
|
||||
defaults['is_cable'] = True
|
||||
defaults['category'] = models.AssetCategory.objects.get(pk=9)
|
||||
|
||||
try:
|
||||
defaults['length'] = child.find('Length_x0020__x0028_m_x0029_').text
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
defaults['status'] = models.AssetStatus.objects.get(pk=int(child.find('Status').text))
|
||||
|
||||
try:
|
||||
defaults['comments'] = child.find('Comments').text
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
collection_id = int(child.find('Collection').text)
|
||||
if collection_id != 0:
|
||||
defaults['collection'] = models.Collection.objects.get(pk=collection_id)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
defaults['purchase_price'] = float(child.find('Purchase_x0020_Price').text)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
defaults['date_acquired'] = self.epoch
|
||||
|
||||
print(defaults)
|
||||
|
||||
obj, created = models.Asset.objects.update_or_create(**defaults)
|
||||
|
||||
if created:
|
||||
tally[1] += 1
|
||||
else:
|
||||
tally[0] += 1
|
||||
|
||||
print('Collections - Updated: {}, Created: {}'.format(tally[0], tally[1]))
|
||||
112
assets/management/commands/update_old_db_file.py
Normal file
112
assets/management/commands/update_old_db_file.py
Normal file
@@ -0,0 +1,112 @@
|
||||
import os
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
from django.conf import settings
|
||||
import datetime
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from assets import models
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = 'Imports old db from XML dump'
|
||||
|
||||
epoch = datetime.date(1970, 1, 1)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
# self.update_statuses()
|
||||
# self.update_suppliers()
|
||||
self.update_cable_statuses()
|
||||
|
||||
@staticmethod
|
||||
def xml_path(file):
|
||||
return os.path.join(settings.BASE_DIR, 'data/DB_Dump/{}'.format(file))
|
||||
|
||||
@staticmethod
|
||||
def parse_xml(file):
|
||||
tree = ET.parse(file)
|
||||
|
||||
return tree.getroot()
|
||||
|
||||
def update_statuses(self):
|
||||
file = self.xml_path('TEC_Assets.xml')
|
||||
tree = ET.parse(file)
|
||||
root = tree.getroot()
|
||||
|
||||
# map old status pk to new status pk
|
||||
status_map = {
|
||||
2: 2,
|
||||
3: 4,
|
||||
4: 3,
|
||||
5: 5,
|
||||
6: 1
|
||||
}
|
||||
|
||||
for child in root:
|
||||
status = int(child.find('StatusID').text)
|
||||
child.find('StatusID').text = str(status_map[status])
|
||||
|
||||
tree.write(file)
|
||||
|
||||
def update_suppliers(self):
|
||||
old_file = self.xml_path('TEC_Asset_Suppliers.xml')
|
||||
old_tree = ET.parse(old_file)
|
||||
old_root = old_tree.getroot()
|
||||
|
||||
new_file = self.xml_path('TEC_Asset_Suppliers_new.xml')
|
||||
new_tree = ET.parse(new_file)
|
||||
new_root = new_tree.getroot()
|
||||
|
||||
# map old supplier pk to new supplier pk
|
||||
supplier_map = dict()
|
||||
|
||||
def find_in_old(name, root):
|
||||
for child in root:
|
||||
found_id = child.find('Supplier_x0020_Id').text
|
||||
found_name = child.find('Supplier_x0020_Name').text
|
||||
|
||||
if found_name == name:
|
||||
return found_id
|
||||
|
||||
for new_child in new_root:
|
||||
new_id = new_child.find('Supplier_x0020_Id').text
|
||||
new_name = new_child.find('Supplier_x0020_Name').text
|
||||
|
||||
old_id = find_in_old(new_name, old_root)
|
||||
|
||||
supplier_map[int(old_id)] = int(new_id)
|
||||
|
||||
file = self.xml_path('TEC_Assets.xml')
|
||||
tree = ET.parse(file)
|
||||
root = tree.getroot()
|
||||
|
||||
for child in root:
|
||||
try:
|
||||
supplier = int(child.find('Supplier_x0020_Id').text)
|
||||
child.find('Supplier_x0020_Id').text = str(supplier_map[supplier])
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
tree.write(file)
|
||||
|
||||
def update_cable_statuses(self):
|
||||
file = self.xml_path('TEC_Cables.xml')
|
||||
tree = ET.parse(file)
|
||||
root = tree.getroot()
|
||||
|
||||
# map old status pk to new status pk
|
||||
status_map = {
|
||||
0: 7,
|
||||
1: 3,
|
||||
3: 2,
|
||||
4: 5,
|
||||
6: 6,
|
||||
7: 1,
|
||||
8: 4,
|
||||
9: 2,
|
||||
}
|
||||
|
||||
for child in root:
|
||||
status = int(child.find('Status').text)
|
||||
child.find('Status').text = str(status_map[status])
|
||||
|
||||
tree.write(file)
|
||||
86
assets/migrations/0001_initial.py
Normal file
86
assets/migrations/0001_initial.py
Normal file
@@ -0,0 +1,86 @@
|
||||
# Generated by Django 2.0.2 on 2018-02-28 16:06
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Asset',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('asset_id', models.IntegerField()),
|
||||
('description', models.CharField(max_length=120)),
|
||||
('serial_number', models.CharField(blank=True, max_length=150, null=True)),
|
||||
('date_acquired', models.DateField()),
|
||||
('date_sold', models.DateField(blank=True, null=True)),
|
||||
('purchase_price', models.IntegerField()),
|
||||
('salvage_value', models.IntegerField(blank=True, null=True)),
|
||||
('comments', models.TextField(blank=True, null=True)),
|
||||
('next_sched_maint', models.DateField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AssetCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=80)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Asset Category',
|
||||
'verbose_name_plural': 'Asset Categories',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AssetStatus',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=80)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Asset Status',
|
||||
'verbose_name_plural': 'Asset Statuses',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Collection',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=80)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Supplier',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=80)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='category',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.AssetCategory'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='collection',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Collection'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='purchased_from',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.Supplier'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='status',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.AssetStatus'),
|
||||
),
|
||||
]
|
||||
18
assets/migrations/0002_auto_20180301_1654.py
Normal file
18
assets/migrations/0002_auto_20180301_1654.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.2 on 2018-03-01 16:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.IntegerField(blank=True),
|
||||
),
|
||||
]
|
||||
18
assets/migrations/0003_auto_20180301_1700.py
Normal file
18
assets/migrations/0003_auto_20180301_1700.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.2 on 2018-03-01 17:00
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0002_auto_20180301_1654'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='purchase_price',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
19
assets/migrations/0004_auto_20180301_1711.py
Normal file
19
assets/migrations/0004_auto_20180301_1711.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 2.0.2 on 2018-03-01 17:11
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0003_auto_20180301_1700'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='collection',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.Collection'),
|
||||
),
|
||||
]
|
||||
18
assets/migrations/0005_auto_20180301_1725.py
Normal file
18
assets/migrations/0005_auto_20180301_1725.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.0.2 on 2018-03-01 17:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0004_auto_20180301_1711'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,148 @@
|
||||
# Generated by Django 2.1.5 on 2019-01-05 19:54
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
replaces = [('assets', '0006_auto_20180728_1451'), ('assets', '0007_auto_20181215_1447'), ('assets', '0008_auto_20181215_1448'), ('assets', '0009_auto_20181215_1640'), ('assets', '0010_auto_20181215_1640'), ('assets', '0011_auto_20181215_1749'), ('assets', '0012_auto_20181215_1813'), ('assets', '0013_asset_parent'), ('assets', '0014_auto_20190103_1615'), ('assets', '0015_auto_20190103_1617'), ('assets', '0016_remove_asset_collection'), ('assets', '0017_delete_collection'), ('assets', '0018_auto_20190103_1708'), ('assets', '0019_auto_20190103_1723'), ('assets', '0020_auto_20190103_1729'), ('assets', '0021_auto_20190105_1156')]
|
||||
|
||||
dependencies = [
|
||||
('assets', '0005_auto_20180301_1725'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.IntegerField(blank=True, null=True, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='purchase_price',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='salvage_value',
|
||||
field=models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.IntegerField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='is_cable',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='length',
|
||||
field=models.DecimalField(blank=True, decimal_places=1, max_digits=10, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.CharField(blank=True, max_length=10, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='asset_id',
|
||||
field=models.CharField(default='', max_length=10),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='asset',
|
||||
name='parent',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=None, related_name='asset_parent', to='assets.Asset'),
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='asset',
|
||||
name='collection',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Collection',
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Cable',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('asset_id', models.CharField(max_length=10)),
|
||||
('description', models.CharField(max_length=120)),
|
||||
('serial_number', models.CharField(blank=True, max_length=150, null=True)),
|
||||
('date_acquired', models.DateField()),
|
||||
('date_sold', models.DateField(blank=True, null=True)),
|
||||
('purchase_price', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
|
||||
('salvage_value', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
|
||||
('comments', models.TextField(blank=True, null=True)),
|
||||
('next_sched_maint', models.DateField(blank=True, null=True)),
|
||||
('is_cable', models.BooleanField(default=False)),
|
||||
('length', models.DecimalField(blank=True, decimal_places=1, help_text='m', max_digits=10, null=True)),
|
||||
('csa', models.DecimalField(blank=True, decimal_places=2, help_text='mm^2', max_digits=10, null=True)),
|
||||
('circuits', models.IntegerField(blank=True, null=True)),
|
||||
('cores', models.IntegerField(blank=True, null=True)),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.AssetCategory')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=None, related_name='asset_parent', to='assets.Cable')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Connector',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('description', models.CharField(max_length=80)),
|
||||
('current_rating', models.DecimalField(decimal_places=2, help_text='Amps', max_digits=10)),
|
||||
('voltage_rating', models.IntegerField(default=0, help_text='Volts')),
|
||||
('num_pins', models.IntegerField(blank=True, null=True)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cable',
|
||||
name='plug',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='plug', to='assets.Connector'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cable',
|
||||
name='purchased_from',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.Supplier'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cable',
|
||||
name='socket',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='socket', to='assets.Connector'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='cable',
|
||||
name='status',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.AssetStatus'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='comments',
|
||||
field=models.TextField(blank=True, default=''),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='serial_number',
|
||||
field=models.CharField(blank=True, default='', max_length=150),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cable',
|
||||
name='comments',
|
||||
field=models.TextField(blank=True, default=''),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cable',
|
||||
name='serial_number',
|
||||
field=models.CharField(blank=True, default='', max_length=150),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
29
assets/migrations/0007_auto_20190108_0202.py
Normal file
29
assets/migrations/0007_auto_20190108_0202.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Generated by Django 2.1.5 on 2019-01-08 02:02
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0006_auto_20180728_1451_squashed_0021_auto_20190105_1156'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='asset',
|
||||
name='parent',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='asset_parent', to='assets.Asset'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='cable',
|
||||
name='parent',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='asset_parent', to='assets.Cable'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='connector',
|
||||
name='voltage_rating',
|
||||
field=models.IntegerField(help_text='Volts'),
|
||||
),
|
||||
]
|
||||
0
assets/migrations/__init__.py
Normal file
0
assets/migrations/__init__.py
Normal file
95
assets/models.py
Normal file
95
assets/models.py
Normal file
@@ -0,0 +1,95 @@
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
|
||||
import datetime
|
||||
|
||||
|
||||
class AssetCategory(models.Model):
|
||||
class Meta:
|
||||
verbose_name = 'Asset Category'
|
||||
verbose_name_plural = 'Asset Categories'
|
||||
|
||||
name = models.CharField(max_length=80)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class AssetStatus(models.Model):
|
||||
class Meta:
|
||||
verbose_name = 'Asset Status'
|
||||
verbose_name_plural = 'Asset Statuses'
|
||||
|
||||
name = models.CharField(max_length=80)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class Supplier(models.Model):
|
||||
name = models.CharField(max_length=80)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('supplier_list')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
class BaseAsset(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
parent = models.ForeignKey(to='self', related_name='asset_parent', blank=True, null=True, on_delete=models.SET_NULL)
|
||||
asset_id = models.CharField(max_length=10)
|
||||
description = models.CharField(max_length=120)
|
||||
category = models.ForeignKey(to=AssetCategory, on_delete=models.CASCADE)
|
||||
status = models.ForeignKey(to=AssetStatus, on_delete=models.CASCADE)
|
||||
serial_number = models.CharField(max_length=150, blank=True)
|
||||
purchased_from = models.ForeignKey(to=Supplier, on_delete=models.CASCADE, blank=True, null=True)
|
||||
date_acquired = models.DateField()
|
||||
date_sold = models.DateField(blank=True, null=True)
|
||||
purchase_price = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10)
|
||||
salvage_value = models.DecimalField(blank=True, null=True, decimal_places=2, max_digits=10)
|
||||
comments = models.TextField(blank=True)
|
||||
next_sched_maint = models.DateField(blank=True, null=True)
|
||||
|
||||
# Cable assets
|
||||
is_cable = models.BooleanField(default=False)
|
||||
length = models.DecimalField(decimal_places=1, max_digits=10, blank=True, null=True)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('asset_detail', kwargs={'pk': self.pk})
|
||||
|
||||
def __str__(self):
|
||||
return str(self.asset_id) + ' - ' + self.description
|
||||
|
||||
|
||||
class Asset(BaseAsset):
|
||||
pass
|
||||
|
||||
|
||||
class Connector(models.Model):
|
||||
description = models.CharField(max_length=80)
|
||||
current_rating = models.DecimalField(decimal_places=2, max_digits=10, help_text='Amps')
|
||||
voltage_rating = models.IntegerField(help_text='Volts')
|
||||
num_pins = models.IntegerField(blank=True, null=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.description
|
||||
|
||||
|
||||
class Cable(BaseAsset):
|
||||
plug = models.ForeignKey(Connector, on_delete=models.SET_NULL, related_name='plug', null=True)
|
||||
socket = models.ForeignKey(Connector, on_delete=models.SET_NULL, related_name='socket', null=True)
|
||||
length = models.DecimalField(decimal_places=1, max_digits=10, blank=True, null=True, help_text='m')
|
||||
csa = models.DecimalField(decimal_places=2, max_digits=10, blank=True, null=True, help_text='mm^2')
|
||||
circuits = models.IntegerField(blank=True, null=True)
|
||||
cores = models.IntegerField(blank=True, null=True)
|
||||
|
||||
def cable_resistance(self):
|
||||
rho = 0.0000000168
|
||||
return (rho * self.length) / (self.csa * 1000000)
|
||||
|
||||
def __str__(self):
|
||||
return '{} - {}m - {}'.format(self.plug, self.length, self.socket)
|
||||
BIN
assets/static/fonts/Roboto/Roboto-Black.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Black.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-BlackItalic.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-BlackItalic.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-Bold.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Bold.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-BoldItalic.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-BoldItalic.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-Italic.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Italic.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-Light.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Light.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-LightItalic.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-LightItalic.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-Medium.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Medium.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-MediumItalic.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-MediumItalic.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-Regular.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Regular.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-Thin.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-Thin.ttf
Executable file
Binary file not shown.
BIN
assets/static/fonts/Roboto/Roboto-ThinItalic.ttf
Executable file
BIN
assets/static/fonts/Roboto/Roboto-ThinItalic.ttf
Executable file
Binary file not shown.
73
assets/static/js/ajax_form.js
Normal file
73
assets/static/js/ajax_form.js
Normal file
@@ -0,0 +1,73 @@
|
||||
function filterAssetTable() {
|
||||
$.ajax({
|
||||
url : "/asset/filter/", // the endpoint
|
||||
type : "POST", // http method
|
||||
data : {
|
||||
form: $('#asset-filter-form').serialize()
|
||||
},
|
||||
traditional: true,
|
||||
|
||||
success : function(data) {
|
||||
// console.log(data);
|
||||
$('#asset_table_body').html(data)
|
||||
},
|
||||
|
||||
error : function(xhr) {console.log(xhr.status + ": " + xhr.responseText)}
|
||||
});
|
||||
}
|
||||
|
||||
function updateAsset() {
|
||||
$.ajax({
|
||||
url : "/asset/update/", // the endpoint
|
||||
type : "POST", // http method
|
||||
data : {
|
||||
form: $('#asset_update_form').serialize()
|
||||
},
|
||||
traditional: true,
|
||||
|
||||
success : function(data) {
|
||||
// console.log(data);
|
||||
window.location.href = data['url'];
|
||||
},
|
||||
|
||||
error : function(xhr) {console.log(xhr.status + ": " + xhr.responseText)}
|
||||
});
|
||||
}
|
||||
|
||||
function formAssetSearch() {
|
||||
$.ajax({
|
||||
url : "/asset/filter/", // the endpoint
|
||||
type : "POST", // http method
|
||||
data : {
|
||||
sender: 'asset_update',
|
||||
form: "csrfmiddlewaretoken=" + $('input[name=csrfmiddlewaretoken]').val() + "&asset_id=" + $('#parent_search').val()
|
||||
},
|
||||
traditional: true,
|
||||
|
||||
success : function(data) {
|
||||
// console.log(data);
|
||||
$('#formAssetSearchResult').html(data);
|
||||
// window.location.href = data['url'];
|
||||
},
|
||||
|
||||
error : function(xhr) {console.log(xhr.status + ": " + xhr.responseText)}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteAsset(asset_id) {
|
||||
$.ajax({
|
||||
url : "/asset/delete/", // the endpoint
|
||||
type : "POST", // http method
|
||||
data : {
|
||||
asset_id: asset_id
|
||||
},
|
||||
traditional: true,
|
||||
|
||||
success : function(data) {
|
||||
// console.log(data);
|
||||
window.location.href = data['url'];
|
||||
},
|
||||
|
||||
error : function(xhr) {console.log(xhr.status + ": " + xhr.responseText)}
|
||||
});
|
||||
}
|
||||
23
assets/static/js/csrf.js
Normal file
23
assets/static/js/csrf.js
Normal file
@@ -0,0 +1,23 @@
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
function getCookie(name) {
|
||||
var cookieValue = null;
|
||||
if (document.cookie && document.cookie != '') {
|
||||
var cookies = document.cookie.split(';');
|
||||
for (var i = 0; i < cookies.length; i++) {
|
||||
var cookie = jQuery.trim(cookies[i]);
|
||||
// Does this cookie string begin with the name we want?
|
||||
if (cookie.substring(0, name.length + 1) == (name + '=')) {
|
||||
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cookieValue;
|
||||
}
|
||||
if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
|
||||
// Only send the token to relative URLs i.e. locally.
|
||||
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
|
||||
}
|
||||
}
|
||||
});
|
||||
12360
assets/static/js/materialize.js
vendored
Normal file
12360
assets/static/js/materialize.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
assets/static/js/materialize.min.js
vendored
Normal file
6
assets/static/js/materialize.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
55
assets/static/sass/components/_badges.scss
Normal file
55
assets/static/sass/components/_badges.scss
Normal file
@@ -0,0 +1,55 @@
|
||||
// Badges
|
||||
span.badge {
|
||||
min-width: 3rem;
|
||||
padding: 0 6px;
|
||||
margin-left: 14px;
|
||||
text-align: center;
|
||||
font-size: 1rem;
|
||||
line-height: $badge-height;
|
||||
height: $badge-height;
|
||||
color: color('grey', 'darken-1');
|
||||
float: right;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.new {
|
||||
font-weight: 300;
|
||||
font-size: 0.8rem;
|
||||
color: #fff;
|
||||
background-color: $badge-bg-color;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&.new:after {
|
||||
content: " new";
|
||||
}
|
||||
|
||||
&[data-badge-caption]::after {
|
||||
content: " " attr(data-badge-caption);
|
||||
}
|
||||
}
|
||||
|
||||
// Special cases
|
||||
nav ul a span.badge {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
margin-left: 4px;
|
||||
line-height: $badge-height;
|
||||
height: $badge-height;
|
||||
-webkit-font-smoothing: auto;
|
||||
}
|
||||
|
||||
// Line height centering
|
||||
.collection-item span.badge {
|
||||
margin-top: calc(#{$collection-line-height / 2} - #{$badge-height / 2});
|
||||
}
|
||||
.collapsible span.badge {
|
||||
margin-left: auto;
|
||||
}
|
||||
.sidenav span.badge {
|
||||
margin-top: calc(#{$sidenav-line-height / 2} - #{$badge-height / 2});
|
||||
}
|
||||
|
||||
table span.badge {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
margin-left: auto;
|
||||
}
|
||||
322
assets/static/sass/components/_buttons.scss
Normal file
322
assets/static/sass/components/_buttons.scss
Normal file
@@ -0,0 +1,322 @@
|
||||
// shared styles
|
||||
.btn,
|
||||
.btn-flat {
|
||||
border: $button-border;
|
||||
border-radius: $button-radius;
|
||||
display: inline-block;
|
||||
height: $button-height;
|
||||
line-height: $button-height;
|
||||
padding: $button-padding;
|
||||
text-transform: uppercase;
|
||||
vertical-align: middle;
|
||||
-webkit-tap-highlight-color: transparent; // Gets rid of tap active state
|
||||
}
|
||||
|
||||
// Disabled shared style
|
||||
.btn.disabled,
|
||||
.btn-floating.disabled,
|
||||
.btn-large.disabled,
|
||||
.btn-small.disabled,
|
||||
.btn-flat.disabled,
|
||||
.btn:disabled,
|
||||
.btn-floating:disabled,
|
||||
.btn-large:disabled,
|
||||
.btn-small:disabled,
|
||||
.btn-flat:disabled,
|
||||
.btn[disabled],
|
||||
.btn-floating[disabled],
|
||||
.btn-large[disabled],
|
||||
.btn-small[disabled],
|
||||
.btn-flat[disabled] {
|
||||
pointer-events: none;
|
||||
background-color: $button-disabled-background !important;
|
||||
box-shadow: none;
|
||||
color: $button-disabled-color !important;
|
||||
cursor: default;
|
||||
&:hover {
|
||||
background-color: $button-disabled-background !important;
|
||||
color: $button-disabled-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
// Shared icon styles
|
||||
.btn,
|
||||
.btn-floating,
|
||||
.btn-large,
|
||||
.btn-small,
|
||||
.btn-flat {
|
||||
font-size: $button-font-size;
|
||||
outline: 0;
|
||||
i {
|
||||
font-size: $button-icon-font-size;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
// Shared focus button style
|
||||
.btn,
|
||||
.btn-floating {
|
||||
&:focus {
|
||||
background-color: darken($button-raised-background, 10%);
|
||||
}
|
||||
}
|
||||
|
||||
// Raised Button
|
||||
.btn {
|
||||
text-decoration: none;
|
||||
color: $button-raised-color;
|
||||
background-color: $button-raised-background;
|
||||
text-align: center;
|
||||
letter-spacing: .5px;
|
||||
@extend .z-depth-1;
|
||||
transition: background-color .2s ease-out;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: $button-raised-background-hover;
|
||||
@extend .z-depth-1-half;
|
||||
}
|
||||
}
|
||||
|
||||
// Floating button
|
||||
.btn-floating {
|
||||
&:hover {
|
||||
background-color: $button-floating-background-hover;
|
||||
@extend .z-depth-1-half;
|
||||
}
|
||||
&:before {
|
||||
border-radius: 0;
|
||||
}
|
||||
&.btn-large {
|
||||
&.halfway-fab {
|
||||
bottom: -$button-floating-large-size / 2;
|
||||
}
|
||||
width: $button-floating-large-size;
|
||||
height: $button-floating-large-size;
|
||||
padding: 0;
|
||||
i {
|
||||
line-height: $button-floating-large-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-small {
|
||||
&.halfway-fab {
|
||||
bottom: -$button-floating-small-size / 2;
|
||||
}
|
||||
width: $button-floating-small-size;
|
||||
height: $button-floating-small-size;
|
||||
i {
|
||||
line-height: $button-floating-small-size;
|
||||
}
|
||||
}
|
||||
|
||||
&.halfway-fab {
|
||||
&.left {
|
||||
right: auto;
|
||||
left: 24px;
|
||||
}
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
bottom: -$button-floating-size / 2;
|
||||
}
|
||||
display: inline-block;
|
||||
color: $button-floating-color;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
z-index: 1;
|
||||
width: $button-floating-size;
|
||||
height: $button-floating-size;
|
||||
line-height: $button-floating-size;
|
||||
padding: 0;
|
||||
background-color: $button-floating-background;
|
||||
border-radius: $button-floating-radius;
|
||||
@extend .z-depth-1;
|
||||
transition: background-color .3s;
|
||||
cursor: pointer;
|
||||
vertical-align: middle;
|
||||
i {
|
||||
width: inherit;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: $button-floating-color;
|
||||
font-size: $button-large-icon-font-size;
|
||||
line-height: $button-floating-size;
|
||||
}
|
||||
}
|
||||
|
||||
// button fix
|
||||
button.btn-floating {
|
||||
border: $button-border;
|
||||
}
|
||||
|
||||
// Fixed Action Button
|
||||
.fixed-action-btn {
|
||||
&.active {
|
||||
ul {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
// Directions
|
||||
&.direction-left,
|
||||
&.direction-right {
|
||||
padding: 0 0 0 15px;
|
||||
ul {
|
||||
text-align: right;
|
||||
right: 64px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
height: 100%;
|
||||
left: auto;
|
||||
/*width 100% only goes to width of button container */
|
||||
width: 500px;
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 7.5px 15px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.direction-right {
|
||||
padding: 0 15px 0 0;
|
||||
ul {
|
||||
text-align: left;
|
||||
direction: rtl;
|
||||
left: 64px;
|
||||
right: auto;
|
||||
li {
|
||||
margin: 7.5px 0 0 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.direction-bottom {
|
||||
padding: 0 0 15px 0;
|
||||
ul {
|
||||
top: 64px;
|
||||
bottom: auto;
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
li {
|
||||
margin: 15px 0 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.toolbar {
|
||||
&.active {
|
||||
&>a i {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
padding: 0;
|
||||
height: $button-floating-large-size;
|
||||
ul {
|
||||
display: flex;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
li {
|
||||
flex: 1;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
transition: none;
|
||||
a {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
color: #fff;
|
||||
line-height: $button-floating-large-size;
|
||||
z-index: 1;
|
||||
i {
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
position: fixed;
|
||||
right: 23px;
|
||||
bottom: 23px;
|
||||
padding-top: 15px;
|
||||
margin-bottom: 0;
|
||||
z-index: 997;
|
||||
ul {
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
bottom: 64px;
|
||||
margin: 0;
|
||||
visibility: hidden;
|
||||
li {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
a.btn-floating {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.fab-backdrop {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
width: $button-floating-size;
|
||||
height: $button-floating-size;
|
||||
background-color: $button-floating-background;
|
||||
border-radius: $button-floating-radius;
|
||||
transform: scale(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Flat button
|
||||
.btn-flat {
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
color: $button-flat-color;
|
||||
cursor: pointer;
|
||||
transition: background-color .2s;
|
||||
&:focus,
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
&:focus {
|
||||
background-color: rgba(0, 0, 0, .1);
|
||||
}
|
||||
&.disabled,
|
||||
&.btn-flat[disabled] {
|
||||
background-color: transparent !important;
|
||||
color: $button-flat-disabled-color !important;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
// Large button
|
||||
.btn-large {
|
||||
@extend .btn;
|
||||
height: $button-large-height;
|
||||
line-height: $button-large-height;
|
||||
font-size: $button-large-font-size;
|
||||
padding: 0 28px;
|
||||
|
||||
i {
|
||||
font-size: $button-large-icon-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// Small button
|
||||
.btn-small {
|
||||
@extend .btn;
|
||||
height: $button-small-height;
|
||||
line-height: $button-small-height;
|
||||
font-size: $button-small-font-size;
|
||||
i {
|
||||
font-size: $button-small-icon-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// Block button
|
||||
.btn-block {
|
||||
display: block;
|
||||
}
|
||||
195
assets/static/sass/components/_cards.scss
Normal file
195
assets/static/sass/components/_cards.scss
Normal file
@@ -0,0 +1,195 @@
|
||||
|
||||
|
||||
.card-panel {
|
||||
transition: box-shadow .25s;
|
||||
padding: $card-padding;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
border-radius: 2px;
|
||||
@extend .z-depth-1;
|
||||
background-color: $card-bg-color;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
background-color: $card-bg-color;
|
||||
transition: box-shadow .25s;
|
||||
border-radius: 2px;
|
||||
@extend .z-depth-1;
|
||||
|
||||
|
||||
.card-title {
|
||||
font-size: 24px;
|
||||
font-weight: 300;
|
||||
&.activator {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// Card Sizes
|
||||
&.small, &.medium, &.large {
|
||||
position: relative;
|
||||
|
||||
.card-image {
|
||||
max-height: 60%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card-image + .card-content {
|
||||
max-height: 40%;
|
||||
}
|
||||
.card-content {
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.card-action {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
&.medium {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
&.large {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
// Horizontal Cards
|
||||
&.horizontal {
|
||||
&.small, &.medium, &.large {
|
||||
.card-image {
|
||||
height: 100%;
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
display: flex;
|
||||
|
||||
.card-image {
|
||||
max-width: 50%;
|
||||
img {
|
||||
border-radius: 2px 0 0 2px;
|
||||
max-width: 100%;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.card-stacked {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.card-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sticky Action Section
|
||||
&.sticky-action {
|
||||
.card-action {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.card-reveal {
|
||||
z-index: 1;
|
||||
padding-bottom: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.card-image {
|
||||
position: relative;
|
||||
|
||||
// Image background for content
|
||||
img {
|
||||
display: block;
|
||||
border-radius: 2px 2px 0 0;
|
||||
position: relative;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
color: $card-bg-color;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
max-width: 100%;
|
||||
padding: $card-padding;
|
||||
}
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: $card-padding;
|
||||
border-radius: 0 0 2px 2px;
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
.card-title {
|
||||
display: block;
|
||||
line-height: 32px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
i {
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.card-action {
|
||||
&:last-child {
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
background-color: inherit; // Use inherit to inherit color classes
|
||||
border-top: 1px solid rgba(160,160,160,.2);
|
||||
position: relative;
|
||||
padding: 16px $card-padding;
|
||||
|
||||
a:not(.btn):not(.btn-large):not(.btn-floating) {
|
||||
color: $card-link-color;
|
||||
margin-right: $card-padding;
|
||||
transition: color .3s ease;
|
||||
text-transform: uppercase;
|
||||
|
||||
&:hover { color: $card-link-color-light; }
|
||||
}
|
||||
}
|
||||
|
||||
.card-reveal {
|
||||
padding: $card-padding;
|
||||
position: absolute;
|
||||
background-color: $card-bg-color;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
left: 0;
|
||||
top: 100%;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
display: none;
|
||||
|
||||
.card-title {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
90
assets/static/sass/components/_carousel.scss
Normal file
90
assets/static/sass/components/_carousel.scss
Normal file
@@ -0,0 +1,90 @@
|
||||
.carousel {
|
||||
&.carousel-slider {
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
.carousel-fixed-item {
|
||||
&.with-indicators {
|
||||
bottom: 68px;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 20px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: $carousel-height;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: $carousel-height;
|
||||
perspective: 500px;
|
||||
transform-style: preserve-3d;
|
||||
transform-origin: 0% 50%;
|
||||
|
||||
.carousel-item {
|
||||
visibility: hidden;
|
||||
width: $carousel-item-width;
|
||||
height: $carousel-item-height;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
& > img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.indicators {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
|
||||
.indicator-item {
|
||||
&.active {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
margin: 24px 4px;
|
||||
background-color: rgba(255,255,255,.5);
|
||||
|
||||
transition: background-color .3s;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
// Materialbox compatibility
|
||||
&.scrolling .carousel-item .materialboxed,
|
||||
.carousel-item:not(.active) .materialboxed {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
90
assets/static/sass/components/_chips.scss
Normal file
90
assets/static/sass/components/_chips.scss
Normal file
@@ -0,0 +1,90 @@
|
||||
.chip {
|
||||
&:focus {
|
||||
outline: none;
|
||||
background-color: $chip-selected-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: rgba(0,0,0,.6);
|
||||
line-height: 32px;
|
||||
padding: 0 12px;
|
||||
border-radius: 16px;
|
||||
background-color: $chip-bg-color;
|
||||
margin-bottom: $chip-margin;
|
||||
margin-right: $chip-margin;
|
||||
|
||||
> img {
|
||||
float: left;
|
||||
margin: 0 8px 0 -12px;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.close {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.chips {
|
||||
border: none;
|
||||
border-bottom: 1px solid $chip-border-color;
|
||||
box-shadow: none;
|
||||
margin: $input-margin;
|
||||
min-height: 45px;
|
||||
outline: none;
|
||||
transition: all .3s;
|
||||
|
||||
&.focus {
|
||||
border-bottom: 1px solid $chip-selected-color;
|
||||
box-shadow: 0 1px 0 0 $chip-selected-color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.input {
|
||||
background: none;
|
||||
border: 0;
|
||||
color: rgba(0,0,0,.6);
|
||||
display: inline-block;
|
||||
font-size: $input-font-size;
|
||||
height: $input-height;
|
||||
line-height: 32px;
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
padding: 0 !important;
|
||||
width: 120px !important;
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
border: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
// Autocomplete
|
||||
.autocomplete-content {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Form prefix
|
||||
.prefix ~ .chips {
|
||||
margin-left: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
.chips:empty ~ label {
|
||||
font-size: 0.8rem;
|
||||
transform: translateY(-140%);
|
||||
}
|
||||
91
assets/static/sass/components/_collapsible.scss
Normal file
91
assets/static/sass/components/_collapsible.scss
Normal file
@@ -0,0 +1,91 @@
|
||||
.collapsible {
|
||||
border-top: 1px solid $collapsible-border-color;
|
||||
border-right: 1px solid $collapsible-border-color;
|
||||
border-left: 1px solid $collapsible-border-color;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
@extend .z-depth-1;
|
||||
}
|
||||
|
||||
.collapsible-header {
|
||||
&:focus {
|
||||
outline: 0
|
||||
}
|
||||
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
line-height: 1.5;
|
||||
padding: 1rem;
|
||||
background-color: $collapsible-header-color;
|
||||
border-bottom: 1px solid $collapsible-border-color;
|
||||
|
||||
i {
|
||||
width: 2rem;
|
||||
font-size: 1.6rem;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
.keyboard-focused .collapsible-header:focus {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.collapsible-body {
|
||||
display: none;
|
||||
border-bottom: 1px solid $collapsible-border-color;
|
||||
box-sizing: border-box;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
// Sidenav collapsible styling
|
||||
.sidenav,
|
||||
.sidenav.fixed {
|
||||
|
||||
.collapsible {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
|
||||
li { padding: 0; }
|
||||
}
|
||||
|
||||
.collapsible-header {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
line-height: inherit;
|
||||
height: inherit;
|
||||
padding: 0 $sidenav-padding;
|
||||
|
||||
&:hover { background-color: rgba(0,0,0,.05); }
|
||||
i { line-height: inherit; }
|
||||
}
|
||||
|
||||
.collapsible-body {
|
||||
border: 0;
|
||||
background-color: $collapsible-header-color;
|
||||
|
||||
li a {
|
||||
padding: 0 (7.5px + $sidenav-padding)
|
||||
0 (15px + $sidenav-padding);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Popout Collapsible
|
||||
|
||||
.collapsible.popout {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
> li {
|
||||
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
|
||||
// transform: scaleX(.92);
|
||||
margin: 0 24px;
|
||||
transition: margin .35s cubic-bezier(0.250, 0.460, 0.450, 0.940);
|
||||
}
|
||||
> li.active {
|
||||
box-shadow: 0 5px 11px 0 rgba(0, 0, 0, 0.18), 0 4px 15px 0 rgba(0, 0, 0, 0.15);
|
||||
margin: 16px 0;
|
||||
// transform: scaleX(1);
|
||||
}
|
||||
}
|
||||
32
assets/static/sass/components/_color-classes.scss
Normal file
32
assets/static/sass/components/_color-classes.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
// Color Classes
|
||||
|
||||
@each $color_name, $color in $colors {
|
||||
@each $color_type, $color_value in $color {
|
||||
@if $color_type == "base" {
|
||||
.#{$color_name} {
|
||||
background-color: $color_value !important;
|
||||
}
|
||||
.#{$color_name}-text {
|
||||
color: $color_value !important;
|
||||
}
|
||||
}
|
||||
@else if $color_name != "shades" {
|
||||
.#{$color_name}.#{$color_type} {
|
||||
background-color: $color_value !important;
|
||||
}
|
||||
.#{$color_name}-text.text-#{$color_type} {
|
||||
color: $color_value !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shade classes
|
||||
@each $color, $color_value in $shades {
|
||||
.#{$color} {
|
||||
background-color: $color_value !important;
|
||||
}
|
||||
.#{$color}-text {
|
||||
color: $color_value !important;
|
||||
}
|
||||
}
|
||||
370
assets/static/sass/components/_color-variables.scss
Normal file
370
assets/static/sass/components/_color-variables.scss
Normal file
@@ -0,0 +1,370 @@
|
||||
// Google Color Palette defined: http://www.google.com/design/spec/style/color.html
|
||||
|
||||
$materialize-red: (
|
||||
"base": #e51c23,
|
||||
"lighten-5": #fdeaeb,
|
||||
"lighten-4": #f8c1c3,
|
||||
"lighten-3": #f3989b,
|
||||
"lighten-2": #ee6e73,
|
||||
"lighten-1": #ea454b,
|
||||
"darken-1": #d0181e,
|
||||
"darken-2": #b9151b,
|
||||
"darken-3": #a21318,
|
||||
"darken-4": #8b1014,
|
||||
);
|
||||
|
||||
$red: (
|
||||
"base": #F44336,
|
||||
"lighten-5": #FFEBEE,
|
||||
"lighten-4": #FFCDD2,
|
||||
"lighten-3": #EF9A9A,
|
||||
"lighten-2": #E57373,
|
||||
"lighten-1": #EF5350,
|
||||
"darken-1": #E53935,
|
||||
"darken-2": #D32F2F,
|
||||
"darken-3": #C62828,
|
||||
"darken-4": #B71C1C,
|
||||
"accent-1": #FF8A80,
|
||||
"accent-2": #FF5252,
|
||||
"accent-3": #FF1744,
|
||||
"accent-4": #D50000
|
||||
);
|
||||
|
||||
$pink: (
|
||||
"base": #e91e63,
|
||||
"lighten-5": #fce4ec,
|
||||
"lighten-4": #f8bbd0,
|
||||
"lighten-3": #f48fb1,
|
||||
"lighten-2": #f06292,
|
||||
"lighten-1": #ec407a,
|
||||
"darken-1": #d81b60,
|
||||
"darken-2": #c2185b,
|
||||
"darken-3": #ad1457,
|
||||
"darken-4": #880e4f,
|
||||
"accent-1": #ff80ab,
|
||||
"accent-2": #ff4081,
|
||||
"accent-3": #f50057,
|
||||
"accent-4": #c51162
|
||||
);
|
||||
|
||||
$purple: (
|
||||
"base": #9c27b0,
|
||||
"lighten-5": #f3e5f5,
|
||||
"lighten-4": #e1bee7,
|
||||
"lighten-3": #ce93d8,
|
||||
"lighten-2": #ba68c8,
|
||||
"lighten-1": #ab47bc,
|
||||
"darken-1": #8e24aa,
|
||||
"darken-2": #7b1fa2,
|
||||
"darken-3": #6a1b9a,
|
||||
"darken-4": #4a148c,
|
||||
"accent-1": #ea80fc,
|
||||
"accent-2": #e040fb,
|
||||
"accent-3": #d500f9,
|
||||
"accent-4": #aa00ff
|
||||
);
|
||||
|
||||
$deep-purple: (
|
||||
"base": #673ab7,
|
||||
"lighten-5": #ede7f6,
|
||||
"lighten-4": #d1c4e9,
|
||||
"lighten-3": #b39ddb,
|
||||
"lighten-2": #9575cd,
|
||||
"lighten-1": #7e57c2,
|
||||
"darken-1": #5e35b1,
|
||||
"darken-2": #512da8,
|
||||
"darken-3": #4527a0,
|
||||
"darken-4": #311b92,
|
||||
"accent-1": #b388ff,
|
||||
"accent-2": #7c4dff,
|
||||
"accent-3": #651fff,
|
||||
"accent-4": #6200ea
|
||||
);
|
||||
|
||||
$indigo: (
|
||||
"base": #3f51b5,
|
||||
"lighten-5": #e8eaf6,
|
||||
"lighten-4": #c5cae9,
|
||||
"lighten-3": #9fa8da,
|
||||
"lighten-2": #7986cb,
|
||||
"lighten-1": #5c6bc0,
|
||||
"darken-1": #3949ab,
|
||||
"darken-2": #303f9f,
|
||||
"darken-3": #283593,
|
||||
"darken-4": #1a237e,
|
||||
"accent-1": #8c9eff,
|
||||
"accent-2": #536dfe,
|
||||
"accent-3": #3d5afe,
|
||||
"accent-4": #304ffe
|
||||
);
|
||||
|
||||
$blue: (
|
||||
"base": #2196F3,
|
||||
"lighten-5": #E3F2FD,
|
||||
"lighten-4": #BBDEFB,
|
||||
"lighten-3": #90CAF9,
|
||||
"lighten-2": #64B5F6,
|
||||
"lighten-1": #42A5F5,
|
||||
"darken-1": #1E88E5,
|
||||
"darken-2": #1976D2,
|
||||
"darken-3": #1565C0,
|
||||
"darken-4": #0D47A1,
|
||||
"accent-1": #82B1FF,
|
||||
"accent-2": #448AFF,
|
||||
"accent-3": #2979FF,
|
||||
"accent-4": #2962FF
|
||||
);
|
||||
|
||||
$light-blue: (
|
||||
"base": #03a9f4,
|
||||
"lighten-5": #e1f5fe,
|
||||
"lighten-4": #b3e5fc,
|
||||
"lighten-3": #81d4fa,
|
||||
"lighten-2": #4fc3f7,
|
||||
"lighten-1": #29b6f6,
|
||||
"darken-1": #039be5,
|
||||
"darken-2": #0288d1,
|
||||
"darken-3": #0277bd,
|
||||
"darken-4": #01579b,
|
||||
"accent-1": #80d8ff,
|
||||
"accent-2": #40c4ff,
|
||||
"accent-3": #00b0ff,
|
||||
"accent-4": #0091ea
|
||||
);
|
||||
|
||||
$cyan: (
|
||||
"base": #00bcd4,
|
||||
"lighten-5": #e0f7fa,
|
||||
"lighten-4": #b2ebf2,
|
||||
"lighten-3": #80deea,
|
||||
"lighten-2": #4dd0e1,
|
||||
"lighten-1": #26c6da,
|
||||
"darken-1": #00acc1,
|
||||
"darken-2": #0097a7,
|
||||
"darken-3": #00838f,
|
||||
"darken-4": #006064,
|
||||
"accent-1": #84ffff,
|
||||
"accent-2": #18ffff,
|
||||
"accent-3": #00e5ff,
|
||||
"accent-4": #00b8d4
|
||||
);
|
||||
|
||||
$teal: (
|
||||
"base": #009688,
|
||||
"lighten-5": #e0f2f1,
|
||||
"lighten-4": #b2dfdb,
|
||||
"lighten-3": #80cbc4,
|
||||
"lighten-2": #4db6ac,
|
||||
"lighten-1": #26a69a,
|
||||
"darken-1": #00897b,
|
||||
"darken-2": #00796b,
|
||||
"darken-3": #00695c,
|
||||
"darken-4": #004d40,
|
||||
"accent-1": #a7ffeb,
|
||||
"accent-2": #64ffda,
|
||||
"accent-3": #1de9b6,
|
||||
"accent-4": #00bfa5
|
||||
);
|
||||
|
||||
$green: (
|
||||
"base": #4CAF50,
|
||||
"lighten-5": #E8F5E9,
|
||||
"lighten-4": #C8E6C9,
|
||||
"lighten-3": #A5D6A7,
|
||||
"lighten-2": #81C784,
|
||||
"lighten-1": #66BB6A,
|
||||
"darken-1": #43A047,
|
||||
"darken-2": #388E3C,
|
||||
"darken-3": #2E7D32,
|
||||
"darken-4": #1B5E20,
|
||||
"accent-1": #B9F6CA,
|
||||
"accent-2": #69F0AE,
|
||||
"accent-3": #00E676,
|
||||
"accent-4": #00C853
|
||||
);
|
||||
|
||||
$light-green: (
|
||||
"base": #8bc34a,
|
||||
"lighten-5": #f1f8e9,
|
||||
"lighten-4": #dcedc8,
|
||||
"lighten-3": #c5e1a5,
|
||||
"lighten-2": #aed581,
|
||||
"lighten-1": #9ccc65,
|
||||
"darken-1": #7cb342,
|
||||
"darken-2": #689f38,
|
||||
"darken-3": #558b2f,
|
||||
"darken-4": #33691e,
|
||||
"accent-1": #ccff90,
|
||||
"accent-2": #b2ff59,
|
||||
"accent-3": #76ff03,
|
||||
"accent-4": #64dd17
|
||||
);
|
||||
|
||||
$lime: (
|
||||
"base": #cddc39,
|
||||
"lighten-5": #f9fbe7,
|
||||
"lighten-4": #f0f4c3,
|
||||
"lighten-3": #e6ee9c,
|
||||
"lighten-2": #dce775,
|
||||
"lighten-1": #d4e157,
|
||||
"darken-1": #c0ca33,
|
||||
"darken-2": #afb42b,
|
||||
"darken-3": #9e9d24,
|
||||
"darken-4": #827717,
|
||||
"accent-1": #f4ff81,
|
||||
"accent-2": #eeff41,
|
||||
"accent-3": #c6ff00,
|
||||
"accent-4": #aeea00
|
||||
);
|
||||
|
||||
$yellow: (
|
||||
"base": #ffeb3b,
|
||||
"lighten-5": #fffde7,
|
||||
"lighten-4": #fff9c4,
|
||||
"lighten-3": #fff59d,
|
||||
"lighten-2": #fff176,
|
||||
"lighten-1": #ffee58,
|
||||
"darken-1": #fdd835,
|
||||
"darken-2": #fbc02d,
|
||||
"darken-3": #f9a825,
|
||||
"darken-4": #f57f17,
|
||||
"accent-1": #ffff8d,
|
||||
"accent-2": #ffff00,
|
||||
"accent-3": #ffea00,
|
||||
"accent-4": #ffd600
|
||||
);
|
||||
|
||||
$amber: (
|
||||
"base": #ffc107,
|
||||
"lighten-5": #fff8e1,
|
||||
"lighten-4": #ffecb3,
|
||||
"lighten-3": #ffe082,
|
||||
"lighten-2": #ffd54f,
|
||||
"lighten-1": #ffca28,
|
||||
"darken-1": #ffb300,
|
||||
"darken-2": #ffa000,
|
||||
"darken-3": #ff8f00,
|
||||
"darken-4": #ff6f00,
|
||||
"accent-1": #ffe57f,
|
||||
"accent-2": #ffd740,
|
||||
"accent-3": #ffc400,
|
||||
"accent-4": #ffab00
|
||||
);
|
||||
|
||||
$orange: (
|
||||
"base": #ff9800,
|
||||
"lighten-5": #fff3e0,
|
||||
"lighten-4": #ffe0b2,
|
||||
"lighten-3": #ffcc80,
|
||||
"lighten-2": #ffb74d,
|
||||
"lighten-1": #ffa726,
|
||||
"darken-1": #fb8c00,
|
||||
"darken-2": #f57c00,
|
||||
"darken-3": #ef6c00,
|
||||
"darken-4": #e65100,
|
||||
"accent-1": #ffd180,
|
||||
"accent-2": #ffab40,
|
||||
"accent-3": #ff9100,
|
||||
"accent-4": #ff6d00
|
||||
);
|
||||
|
||||
$deep-orange: (
|
||||
"base": #ff5722,
|
||||
"lighten-5": #fbe9e7,
|
||||
"lighten-4": #ffccbc,
|
||||
"lighten-3": #ffab91,
|
||||
"lighten-2": #ff8a65,
|
||||
"lighten-1": #ff7043,
|
||||
"darken-1": #f4511e,
|
||||
"darken-2": #e64a19,
|
||||
"darken-3": #d84315,
|
||||
"darken-4": #bf360c,
|
||||
"accent-1": #ff9e80,
|
||||
"accent-2": #ff6e40,
|
||||
"accent-3": #ff3d00,
|
||||
"accent-4": #dd2c00
|
||||
);
|
||||
|
||||
$brown: (
|
||||
"base": #795548,
|
||||
"lighten-5": #efebe9,
|
||||
"lighten-4": #d7ccc8,
|
||||
"lighten-3": #bcaaa4,
|
||||
"lighten-2": #a1887f,
|
||||
"lighten-1": #8d6e63,
|
||||
"darken-1": #6d4c41,
|
||||
"darken-2": #5d4037,
|
||||
"darken-3": #4e342e,
|
||||
"darken-4": #3e2723
|
||||
);
|
||||
|
||||
$blue-grey: (
|
||||
"base": #607d8b,
|
||||
"lighten-5": #eceff1,
|
||||
"lighten-4": #cfd8dc,
|
||||
"lighten-3": #b0bec5,
|
||||
"lighten-2": #90a4ae,
|
||||
"lighten-1": #78909c,
|
||||
"darken-1": #546e7a,
|
||||
"darken-2": #455a64,
|
||||
"darken-3": #37474f,
|
||||
"darken-4": #263238
|
||||
);
|
||||
|
||||
$grey: (
|
||||
"base": #9e9e9e,
|
||||
"lighten-5": #fafafa,
|
||||
"lighten-4": #f5f5f5,
|
||||
"lighten-3": #eeeeee,
|
||||
"lighten-2": #e0e0e0,
|
||||
"lighten-1": #bdbdbd,
|
||||
"darken-1": #757575,
|
||||
"darken-2": #616161,
|
||||
"darken-3": #424242,
|
||||
"darken-4": #212121
|
||||
);
|
||||
|
||||
$shades: (
|
||||
"black": #000000,
|
||||
"white": #FFFFFF,
|
||||
"transparent": transparent
|
||||
);
|
||||
|
||||
$colors: (
|
||||
"materialize-red": $materialize-red,
|
||||
"red": $red,
|
||||
"pink": $pink,
|
||||
"purple": $purple,
|
||||
"deep-purple": $deep-purple,
|
||||
"indigo": $indigo,
|
||||
"blue": $blue,
|
||||
"light-blue": $light-blue,
|
||||
"cyan": $cyan,
|
||||
"teal": $teal,
|
||||
"green": $green,
|
||||
"light-green": $light-green,
|
||||
"lime": $lime,
|
||||
"yellow": $yellow,
|
||||
"amber": $amber,
|
||||
"orange": $orange,
|
||||
"deep-orange": $deep-orange,
|
||||
"brown": $brown,
|
||||
"blue-grey": $blue-grey,
|
||||
"grey": $grey,
|
||||
"shades": $shades
|
||||
) !default;
|
||||
|
||||
|
||||
// usage: color("name_of_color", "type_of_color")
|
||||
// to avoid to repeating map-get($colors, ...)
|
||||
|
||||
@function color($color, $type) {
|
||||
@if map-has-key($colors, $color) {
|
||||
$curr_color: map-get($colors, $color);
|
||||
@if map-has-key($curr_color, $type) {
|
||||
@return map-get($curr_color, $type);
|
||||
}
|
||||
}
|
||||
@warn "Unknown `#{$color}` - `#{$type}` in $colors.";
|
||||
@return null;
|
||||
}
|
||||
191
assets/static/sass/components/_datepicker.scss
Normal file
191
assets/static/sass/components/_datepicker.scss
Normal file
@@ -0,0 +1,191 @@
|
||||
/* Modal */
|
||||
.datepicker-modal {
|
||||
max-width: 325px;
|
||||
min-width: 300px;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.datepicker-container.modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.datepicker-controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 280px;
|
||||
margin: 0 auto;
|
||||
|
||||
.selects-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.select-wrapper {
|
||||
input {
|
||||
&:focus {
|
||||
border-bottom: none;
|
||||
}
|
||||
border-bottom: none;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.caret {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.select-year input {
|
||||
width: 50px;
|
||||
}
|
||||
|
||||
.select-month input {
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.month-prev, .month-next {
|
||||
margin-top: 4px;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
/* Date Display */
|
||||
.datepicker-date-display {
|
||||
flex: 1 auto;
|
||||
background-color: $secondary-color;
|
||||
color: #fff;
|
||||
padding: 20px 22px;
|
||||
font-weight: 500;
|
||||
|
||||
.year-text {
|
||||
display: block;
|
||||
font-size: 1.5rem;
|
||||
line-height: 25px;
|
||||
color: $datepicker-year;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
display: block;
|
||||
font-size: 2.8rem;
|
||||
line-height: 47px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Calendar */
|
||||
.datepicker-calendar-container {
|
||||
flex: 2.5 auto;
|
||||
}
|
||||
|
||||
.datepicker-table {
|
||||
width: 280px;
|
||||
font-size: 1rem;
|
||||
margin: 0 auto;
|
||||
|
||||
thead {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 10px 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tr {
|
||||
border: none;
|
||||
}
|
||||
|
||||
abbr {
|
||||
text-decoration: none;
|
||||
color: $datepicker-calendar-header-color;
|
||||
}
|
||||
|
||||
td {
|
||||
&.is-today {
|
||||
color: $secondary-color;
|
||||
}
|
||||
|
||||
&.is-selected {
|
||||
background-color: $secondary-color;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.is-outside-current-month,
|
||||
&.is-disabled {
|
||||
color: $datepicker-disabled-day-color;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
border-radius: 50%;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.datepicker-day-button {
|
||||
&:focus {
|
||||
background-color: $datepicker-day-focus;
|
||||
}
|
||||
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
line-height: 38px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-radius: 50%;
|
||||
padding: 0 5px;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
.datepicker-footer {
|
||||
width: 280px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.datepicker-cancel,
|
||||
.datepicker-clear,
|
||||
.datepicker-today,
|
||||
.datepicker-done {
|
||||
color: $secondary-color;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
.datepicker-clear {
|
||||
color: $error-color;
|
||||
}
|
||||
|
||||
|
||||
/* Media Queries */
|
||||
@media #{$medium-and-up} {
|
||||
.datepicker-modal {
|
||||
max-width: 625px;
|
||||
}
|
||||
|
||||
.datepicker-container.modal-content {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.datepicker-date-display {
|
||||
flex: 0 1 270px;
|
||||
}
|
||||
|
||||
.datepicker-controls,
|
||||
.datepicker-table,
|
||||
.datepicker-footer {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
.datepicker-day-button {
|
||||
line-height: 44px;
|
||||
}
|
||||
}
|
||||
85
assets/static/sass/components/_dropdown.scss
Normal file
85
assets/static/sass/components/_dropdown.scss
Normal file
@@ -0,0 +1,85 @@
|
||||
.dropdown-content {
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
|
||||
@extend .z-depth-1;
|
||||
background-color: $dropdown-bg-color;
|
||||
margin: 0;
|
||||
display: none;
|
||||
min-width: 100px;
|
||||
overflow-y: auto;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: -64px;
|
||||
z-index: 9999; // TODO: Check if this doesn't break other things
|
||||
transform-origin: 0 0;
|
||||
|
||||
|
||||
li {
|
||||
&:hover, &.active {
|
||||
background-color: $dropdown-hover-bg-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.divider {
|
||||
min-height: 0;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
& > a, & > span {
|
||||
font-size: 16px;
|
||||
color: $dropdown-color;
|
||||
display: block;
|
||||
line-height: 22px;
|
||||
padding: (($dropdown-item-height - 22) / 2) 16px;
|
||||
}
|
||||
|
||||
& > span > label {
|
||||
top: 1px;
|
||||
left: 0;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
// Icon alignment override
|
||||
& > a > i {
|
||||
height: inherit;
|
||||
line-height: inherit;
|
||||
float: left;
|
||||
margin: 0 24px 0 0;
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
|
||||
clear: both;
|
||||
color: $off-black;
|
||||
cursor: pointer;
|
||||
min-height: $dropdown-item-height;
|
||||
line-height: 1.5rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
body.keyboard-focused {
|
||||
.dropdown-content li:focus {
|
||||
background-color: darken($dropdown-hover-bg-color, 8%);
|
||||
}
|
||||
}
|
||||
|
||||
// Input field specificity bugfix
|
||||
.input-field.col .dropdown-content [type="checkbox"] + label {
|
||||
top: 1px;
|
||||
left: 0;
|
||||
height: 18px;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.dropdown-trigger {
|
||||
cursor: pointer;
|
||||
}
|
||||
769
assets/static/sass/components/_global.scss
Normal file
769
assets/static/sass/components/_global.scss
Normal file
@@ -0,0 +1,769 @@
|
||||
//Default styles
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
body {
|
||||
// display: flex;
|
||||
// min-height: 100vh;
|
||||
// flex-direction: column;
|
||||
}
|
||||
|
||||
main {
|
||||
// flex: 1 0 auto;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: $font-stack;
|
||||
}
|
||||
|
||||
ul {
|
||||
&:not(.browser-default) {
|
||||
padding-left: 0;
|
||||
list-style-type: none;
|
||||
|
||||
& > li {
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $link-color;
|
||||
text-decoration: none;
|
||||
|
||||
// Gets rid of tap active state
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
// Positioning
|
||||
.valign-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
// classic clearfix
|
||||
.clearfix {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
// Z-levels
|
||||
.z-depth-0 {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* 2dp elevation modified*/
|
||||
.z-depth-1 {
|
||||
box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14),
|
||||
0 3px 1px -2px rgba(0,0,0,0.12),
|
||||
0 1px 5px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
.z-depth-1-half {
|
||||
box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.14), 0 1px 7px 0 rgba(0, 0, 0, 0.12), 0 3px 1px -1px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* 6dp elevation modified*/
|
||||
.z-depth-2 {
|
||||
box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14),
|
||||
0 1px 10px 0 rgba(0,0,0,0.12),
|
||||
0 2px 4px -1px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
/* 12dp elevation modified*/
|
||||
.z-depth-3 {
|
||||
box-shadow: 0 8px 17px 2px rgba(0,0,0,0.14),
|
||||
0 3px 14px 2px rgba(0,0,0,0.12),
|
||||
0 5px 5px -3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* 16dp elevation */
|
||||
.z-depth-4 {
|
||||
box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14),
|
||||
0 6px 30px 5px rgba(0,0,0,0.12),
|
||||
0 8px 10px -7px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
/* 24dp elevation */
|
||||
.z-depth-5 {
|
||||
box-shadow: 0 24px 38px 3px rgba(0,0,0,0.14),
|
||||
0 9px 46px 8px rgba(0,0,0,0.12),
|
||||
0 11px 15px -7px rgba(0,0,0,0.2);
|
||||
}
|
||||
|
||||
.hoverable {
|
||||
transition: box-shadow .25s;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 8px 17px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
|
||||
}
|
||||
}
|
||||
|
||||
// Dividers
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: color("grey", "lighten-2");
|
||||
}
|
||||
|
||||
|
||||
// Blockquote
|
||||
|
||||
blockquote {
|
||||
margin: 20px 0;
|
||||
padding-left: 1.5rem;
|
||||
border-left: 5px solid $primary-color;
|
||||
}
|
||||
|
||||
// Icon Styles
|
||||
|
||||
i {
|
||||
line-height: inherit;
|
||||
|
||||
&.left {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
&.right {
|
||||
float: right;
|
||||
margin-left: 15px;
|
||||
}
|
||||
&.tiny {
|
||||
font-size: 1rem;
|
||||
}
|
||||
&.small {
|
||||
font-size: 2rem;
|
||||
}
|
||||
&.medium {
|
||||
font-size: 4rem;
|
||||
}
|
||||
&.large {
|
||||
font-size: 6rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Images
|
||||
img.responsive-img,
|
||||
video.responsive-video {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
|
||||
// Pagination
|
||||
|
||||
.pagination {
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
border-radius: 2px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
height: 30px;
|
||||
|
||||
a {
|
||||
color: #444;
|
||||
display: inline-block;
|
||||
font-size: 1.2rem;
|
||||
padding: 0 10px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
&.active a { color: #fff; }
|
||||
|
||||
&.active { background-color: $primary-color; }
|
||||
|
||||
&.disabled a {
|
||||
cursor: default;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
li.pages ul li {
|
||||
display: inline-block;
|
||||
float: none;
|
||||
}
|
||||
}
|
||||
@media #{$medium-and-down} {
|
||||
.pagination {
|
||||
width: 100%;
|
||||
|
||||
li.prev,
|
||||
li.next {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
li.pages {
|
||||
width: 80%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Breadcrumbs
|
||||
.breadcrumb {
|
||||
font-size: 18px;
|
||||
color: rgba(255,255,255, .7);
|
||||
|
||||
i,
|
||||
[class^="mdi-"], [class*="mdi-"],
|
||||
i.material-icons {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: '\E5CC';
|
||||
color: rgba(255,255,255, .7);
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 25px;
|
||||
margin: 0 10px 0 8px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
&:first-child:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Parallax
|
||||
.parallax-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 500px;
|
||||
|
||||
.parallax {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
|
||||
img {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 0;
|
||||
min-width: 100%;
|
||||
min-height: 100%;
|
||||
transform: translate3d(0,0,0);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pushpin
|
||||
.pin-top, .pin-bottom {
|
||||
position: relative;
|
||||
}
|
||||
.pinned {
|
||||
position: fixed !important;
|
||||
}
|
||||
|
||||
/*********************
|
||||
Transition Classes
|
||||
**********************/
|
||||
|
||||
ul.staggered-list li {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.fade-in {
|
||||
opacity: 0;
|
||||
transform-origin: 0 50%;
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
Media Query Classes
|
||||
**********************/
|
||||
.hide-on-small-only, .hide-on-small-and-down {
|
||||
@media #{$small-and-down} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-med-and-down {
|
||||
@media #{$medium-and-down} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-med-and-up {
|
||||
@media #{$medium-and-up} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-med-only {
|
||||
@media only screen and (min-width: $small-screen) and (max-width: $medium-screen) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-large-only {
|
||||
@media #{$large-and-up} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.hide-on-extra-large-only {
|
||||
@media #{$extra-large-and-up} {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
.show-on-extra-large {
|
||||
@media #{$extra-large-and-up} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-large {
|
||||
@media #{$large-and-up} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-medium {
|
||||
@media only screen and (min-width: $small-screen) and (max-width: $medium-screen) {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-small {
|
||||
@media #{$small-and-down} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-medium-and-up {
|
||||
@media #{$medium-and-up} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
.show-on-medium-and-down {
|
||||
@media #{$medium-and-down} {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Center text on mobile
|
||||
.center-on-small-only {
|
||||
@media #{$small-and-down} {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// Footer
|
||||
.page-footer {
|
||||
padding-top: 20px;
|
||||
color: $footer-font-color;
|
||||
background-color: $footer-bg-color;
|
||||
|
||||
.footer-copyright {
|
||||
overflow: hidden;
|
||||
min-height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0px;
|
||||
color: $footer-copyright-font-color;
|
||||
background-color: $footer-copyright-bg-color;
|
||||
}
|
||||
}
|
||||
|
||||
// Tables
|
||||
table, th, td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
table {
|
||||
width:100%;
|
||||
display: table;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
|
||||
&.striped {
|
||||
tr {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
> tbody {
|
||||
> tr:nth-child(odd) {
|
||||
background-color: $table-striped-color;
|
||||
}
|
||||
|
||||
> tr > td {
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.highlight > tbody > tr {
|
||||
transition: background-color .25s ease;
|
||||
&:hover {
|
||||
background-color: $table-striped-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.centered {
|
||||
thead tr th, tbody tr td {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid $table-border-color;
|
||||
}
|
||||
|
||||
td, th{
|
||||
padding: 15px 5px;
|
||||
display: table-cell;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
// Responsive Table
|
||||
@media #{$medium-and-down} {
|
||||
|
||||
table.responsive-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
td:empty:before {
|
||||
content: '\00a0';
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
margin: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th { text-align: left; }
|
||||
thead {
|
||||
display: block;
|
||||
float: left;
|
||||
|
||||
tr {
|
||||
display: block;
|
||||
padding: 0 10px 0 0;
|
||||
|
||||
th::before {
|
||||
content: "\00a0";
|
||||
}
|
||||
}
|
||||
}
|
||||
tbody {
|
||||
display: block;
|
||||
width: auto;
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
|
||||
tr {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
th {
|
||||
display: block;
|
||||
text-align: right;
|
||||
}
|
||||
td {
|
||||
display: block;
|
||||
min-height: 1.25em;
|
||||
text-align: left;
|
||||
}
|
||||
tr {
|
||||
border-bottom: none;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* sort out borders */
|
||||
thead {
|
||||
border: 0;
|
||||
border-right: 1px solid $table-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Collections
|
||||
.collection {
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
border: 1px solid $collection-border-color;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.collection-item {
|
||||
background-color: $collection-bg-color;
|
||||
line-height: $collection-line-height;
|
||||
padding: 10px 20px;
|
||||
margin: 0;
|
||||
border-bottom: 1px solid $collection-border-color;
|
||||
|
||||
// Avatar Collection
|
||||
&.avatar {
|
||||
min-height: 84px;
|
||||
padding-left: 72px;
|
||||
position: relative;
|
||||
|
||||
// Don't style circles inside preloader classes.
|
||||
&:not(.circle-clipper) > .circle,
|
||||
:not(.circle-clipper) > .circle {
|
||||
position: absolute;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
overflow: hidden;
|
||||
left: 15px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
i.circle {
|
||||
font-size: 18px;
|
||||
line-height: 42px;
|
||||
color: #fff;
|
||||
background-color: #999;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.secondary-content {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $collection-active-bg-color;
|
||||
color: $collection-active-color;
|
||||
|
||||
.secondary-content {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
a.collection-item{
|
||||
display: block;
|
||||
transition: .25s;
|
||||
color: $collection-link-color;
|
||||
&:not(.active) {
|
||||
&:hover {
|
||||
background-color: $collection-hover-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.with-header {
|
||||
.collection-header {
|
||||
background-color: $collection-bg-color;
|
||||
border-bottom: 1px solid $collection-border-color;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
.collection-item {
|
||||
padding-left: 30px;
|
||||
}
|
||||
.collection-item.avatar {
|
||||
padding-left: 72px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Made less specific to allow easier overriding
|
||||
.secondary-content {
|
||||
float: right;
|
||||
color: $secondary-color;
|
||||
}
|
||||
.collapsible .collection {
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Responsive Videos
|
||||
.video-container {
|
||||
position: relative;
|
||||
padding-bottom: 56.25%;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
|
||||
iframe, object, embed {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Progress Bar
|
||||
.progress {
|
||||
position: relative;
|
||||
height: 4px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
background-color: lighten($progress-bar-color, 40%);
|
||||
border-radius: 2px;
|
||||
margin: $element-top-margin 0 $element-bottom-margin 0;
|
||||
overflow: hidden;
|
||||
.determinate {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background-color: $progress-bar-color;
|
||||
transition: width .3s linear;
|
||||
}
|
||||
.indeterminate {
|
||||
background-color: $progress-bar-color;
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left:0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
// Custom bezier
|
||||
animation: indeterminate 2.1s cubic-bezier(0.650, 0.815, 0.735, 0.395) infinite;
|
||||
|
||||
}
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background-color: inherit;
|
||||
top: 0;
|
||||
left:0;
|
||||
bottom: 0;
|
||||
will-change: left, right;
|
||||
// Custom bezier
|
||||
animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.840, 0.440, 1.000) infinite;
|
||||
animation-delay: 1.15s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@keyframes indeterminate {
|
||||
0% {
|
||||
left: -35%;
|
||||
right:100%;
|
||||
}
|
||||
60% {
|
||||
left: 100%;
|
||||
right: -90%;
|
||||
}
|
||||
100% {
|
||||
left: 100%;
|
||||
right: -90%;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes indeterminate-short {
|
||||
0% {
|
||||
left: -200%;
|
||||
right: 100%;
|
||||
}
|
||||
60% {
|
||||
left: 107%;
|
||||
right: -8%;
|
||||
}
|
||||
100% {
|
||||
left: 107%;
|
||||
right: -8%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************
|
||||
Utility Classes
|
||||
*******************/
|
||||
|
||||
.hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
// Text Align
|
||||
.left-align {
|
||||
text-align: left;
|
||||
}
|
||||
.right-align {
|
||||
text-align: right
|
||||
}
|
||||
.center, .center-align {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.left {
|
||||
float: left !important;
|
||||
}
|
||||
.right {
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
// No Text Select
|
||||
.no-select {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.center-block {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0 !important;
|
||||
}
|
||||
156
assets/static/sass/components/_grid.scss
Normal file
156
assets/static/sass/components/_grid.scss
Normal file
@@ -0,0 +1,156 @@
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
max-width: 1280px;
|
||||
width: 90%;
|
||||
}
|
||||
@media #{$medium-and-up} {
|
||||
.container {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
@media #{$large-and-up} {
|
||||
.container {
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
.col .row {
|
||||
margin-left: (-1 * $gutter-width / 2);
|
||||
margin-right: (-1 * $gutter-width / 2);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-top: 1rem;
|
||||
padding-bottom: 1rem;
|
||||
|
||||
&.no-pad {
|
||||
padding: 0;
|
||||
}
|
||||
&.no-pad-bot {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
&.no-pad-top {
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Mixins to eliminate code repitition
|
||||
@mixin reset-offset {
|
||||
margin-left: auto;
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
@mixin grid-classes($size, $i, $perc) {
|
||||
&.offset-#{$size}#{$i} {
|
||||
margin-left: $perc;
|
||||
}
|
||||
&.pull-#{$size}#{$i} {
|
||||
right: $perc;
|
||||
}
|
||||
&.push-#{$size}#{$i} {
|
||||
left: $perc;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.row {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 20px;
|
||||
|
||||
// Clear floating children
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.col {
|
||||
float: left;
|
||||
box-sizing: border-box;
|
||||
padding: 0 $gutter-width / 2;
|
||||
min-height: 1px;
|
||||
|
||||
&[class*="push-"],
|
||||
&[class*="pull-"] {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
&.s#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
@include grid-classes("s", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
@media #{$medium-and-up} {
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
&.m#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
@include grid-classes("m", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$large-and-up} {
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
&.l#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
@include grid-classes("l", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$extra-large-and-up} {
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
&.xl#{$i} {
|
||||
width: $perc;
|
||||
@include reset-offset;
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
$i: 1;
|
||||
@while $i <= $num-cols {
|
||||
$perc: unquote((100 / ($num-cols / $i)) + "%");
|
||||
@include grid-classes("xl", $i, $perc);
|
||||
$i: $i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
/* This is needed for some mobile phones to display the Google Icon font properly */
|
||||
.material-icons {
|
||||
text-rendering: optimizeLegibility;
|
||||
font-feature-settings: 'liga';
|
||||
}
|
||||
43
assets/static/sass/components/_materialbox.scss
Normal file
43
assets/static/sass/components/_materialbox.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
.materialboxed {
|
||||
&:hover {
|
||||
&:not(.active) {
|
||||
opacity: .8;
|
||||
}
|
||||
}
|
||||
|
||||
display: block;
|
||||
cursor: zoom-in;
|
||||
position: relative;
|
||||
transition: opacity .4s;
|
||||
-webkit-backface-visibility: hidden;
|
||||
|
||||
&.active {
|
||||
cursor: zoom-out;
|
||||
}
|
||||
}
|
||||
|
||||
#materialbox-overlay {
|
||||
position:fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: #292929;
|
||||
z-index: 1000;
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
.materialbox-caption {
|
||||
position: fixed;
|
||||
display: none;
|
||||
color: #fff;
|
||||
line-height: 50px;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding: 0% 15%;
|
||||
height: 50px;
|
||||
z-index: 1000;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
16
assets/static/sass/components/_mixins.scss
Normal file
16
assets/static/sass/components/_mixins.scss
Normal file
@@ -0,0 +1,16 @@
|
||||
@mixin clearfix() {
|
||||
&:before,
|
||||
&:after {
|
||||
content: " "; // 1
|
||||
display: table; // 2
|
||||
}
|
||||
&:after {
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin text-overflow() {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
94
assets/static/sass/components/_modal.scss
Normal file
94
assets/static/sass/components/_modal.scss
Normal file
@@ -0,0 +1,94 @@
|
||||
.modal {
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
@extend .z-depth-5;
|
||||
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fafafa;
|
||||
padding: 0;
|
||||
max-height: 70%;
|
||||
width: 55%;
|
||||
margin: auto;
|
||||
overflow-y: auto;
|
||||
|
||||
border-radius: 2px;
|
||||
will-change: top, opacity;
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
padding: 24px;
|
||||
}
|
||||
.modal-close {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-radius: 0 0 2px 2px;
|
||||
background-color: #fafafa;
|
||||
padding: 4px 6px;
|
||||
height: 56px;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
|
||||
.btn, .btn-flat {
|
||||
margin: 6px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-overlay {
|
||||
position: fixed;
|
||||
z-index: 999;
|
||||
top: -25%;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 125%;
|
||||
width: 100%;
|
||||
background: #000;
|
||||
display: none;
|
||||
|
||||
will-change: opacity;
|
||||
}
|
||||
|
||||
// Modal with fixed action footer
|
||||
.modal.modal-fixed-footer {
|
||||
padding: 0;
|
||||
height: 70%;
|
||||
|
||||
.modal-content {
|
||||
position: absolute;
|
||||
height: calc(100% - 56px);
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-top: 1px solid rgba(0,0,0,.1);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Modal Bottom Sheet Style
|
||||
.modal.bottom-sheet {
|
||||
top: auto;
|
||||
bottom: -100%;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-height: 45%;
|
||||
border-radius: 0;
|
||||
will-change: bottom, opacity;
|
||||
}
|
||||
208
assets/static/sass/components/_navbar.scss
Normal file
208
assets/static/sass/components/_navbar.scss
Normal file
@@ -0,0 +1,208 @@
|
||||
nav {
|
||||
&.nav-extended {
|
||||
height: auto;
|
||||
|
||||
.nav-wrapper {
|
||||
min-height: $navbar-height-mobile;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.nav-content {
|
||||
position: relative;
|
||||
line-height: normal;
|
||||
}
|
||||
}
|
||||
|
||||
color: $navbar-font-color;
|
||||
@extend .z-depth-1;
|
||||
background-color: $primary-color;
|
||||
width: 100%;
|
||||
height: $navbar-height-mobile;
|
||||
line-height: $navbar-line-height-mobile;
|
||||
|
||||
a { color: $navbar-font-color; }
|
||||
|
||||
i,
|
||||
[class^="mdi-"], [class*="mdi-"],
|
||||
i.material-icons {
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
height: $navbar-height-mobile;
|
||||
line-height: $navbar-line-height-mobile;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media #{$large-and-up} {
|
||||
a.sidenav-trigger { display: none; }
|
||||
}
|
||||
|
||||
|
||||
// Collapse button
|
||||
.sidenav-trigger {
|
||||
float: left;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
height: $navbar-height-mobile;
|
||||
margin: 0 18px;
|
||||
|
||||
i {
|
||||
height: $navbar-height-mobile;
|
||||
line-height: $navbar-line-height-mobile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Logo
|
||||
.brand-logo {
|
||||
position: absolute;
|
||||
color: $navbar-font-color;
|
||||
display: inline-block;
|
||||
font-size: $navbar-brand-font-size;
|
||||
padding: 0;
|
||||
|
||||
&.center {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
|
||||
&.left, &.right {
|
||||
padding: 0;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
&.left { left: 0.5rem; }
|
||||
&.right {
|
||||
right: 0.5rem;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.right {
|
||||
right: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
i,
|
||||
[class^="mdi-"], [class*="mdi-"],
|
||||
i.material-icons {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Title
|
||||
.nav-title {
|
||||
display: inline-block;
|
||||
font-size: 32px;
|
||||
padding: 28px 0;
|
||||
}
|
||||
|
||||
|
||||
// Navbar Links
|
||||
ul {
|
||||
margin: 0;
|
||||
|
||||
li {
|
||||
transition: background-color .3s;
|
||||
float: left;
|
||||
padding: 0;
|
||||
|
||||
&.active {
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
a {
|
||||
transition: background-color .3s;
|
||||
font-size: $navbar-font-size;
|
||||
color: $navbar-font-color;
|
||||
display: block;
|
||||
padding: 0 15px;
|
||||
cursor: pointer;
|
||||
|
||||
&.btn, &.btn-large, &.btn-flat, &.btn-floating {
|
||||
margin-top: -2px;
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
|
||||
& > .material-icons {
|
||||
height: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
// Navbar Search Form
|
||||
form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
|
||||
input {
|
||||
height: 100%;
|
||||
font-size: 1.2rem;
|
||||
border: none;
|
||||
padding-left: 2rem;
|
||||
|
||||
&:focus, &[type=text]:valid, &[type=password]:valid,
|
||||
&[type=email]:valid, &[type=url]:valid, &[type=date]:valid {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
i {
|
||||
color: rgba(255,255,255,.7);
|
||||
transition: color .3s;
|
||||
}
|
||||
&.active i { color: $navbar-font-color; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed Navbar
|
||||
.navbar-fixed {
|
||||
position: relative;
|
||||
height: $navbar-height-mobile;
|
||||
z-index: 997;
|
||||
|
||||
nav {
|
||||
position: fixed;
|
||||
}
|
||||
}
|
||||
@media #{$medium-and-up} {
|
||||
nav.nav-extended .nav-wrapper {
|
||||
min-height: $navbar-height;
|
||||
}
|
||||
nav, nav .nav-wrapper i, nav a.sidenav-trigger, nav a.sidenav-trigger i {
|
||||
height: $navbar-height;
|
||||
line-height: $navbar-line-height;
|
||||
}
|
||||
.navbar-fixed {
|
||||
height: $navbar-height;
|
||||
}
|
||||
}
|
||||
447
assets/static/sass/components/_normalize.scss
Normal file
447
assets/static/sass/components/_normalize.scss
Normal file
@@ -0,0 +1,447 @@
|
||||
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/* Document
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Correct the line height in all browsers.
|
||||
* 2. Prevent adjustments of font size after orientation changes in
|
||||
* IE on Windows Phone and in iOS.
|
||||
*/
|
||||
|
||||
html {
|
||||
line-height: 1.15; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/* Sections
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the margin in all browsers (opinionated).
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
footer,
|
||||
header,
|
||||
nav,
|
||||
section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the font size and margin on `h1` elements within `section` and
|
||||
* `article` contexts in Chrome, Firefox, and Safari.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in IE.
|
||||
*/
|
||||
|
||||
figcaption,
|
||||
figure,
|
||||
main { /* 1 */
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct margin in IE 8.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in Firefox.
|
||||
* 2. Show the overflow in Edge and IE.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box; /* 1 */
|
||||
height: 0; /* 1 */
|
||||
overflow: visible; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Remove the gray background on active links in IE 10.
|
||||
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent; /* 1 */
|
||||
-webkit-text-decoration-skip: objects; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
|
||||
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: none; /* 1 */
|
||||
text-decoration: underline; /* 2 */
|
||||
text-decoration: underline dotted; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font weight in Chrome, Edge, and Safari.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inheritance and scaling of font size in all browsers.
|
||||
* 2. Correct the odd `em` font sizing in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: monospace, monospace; /* 1 */
|
||||
font-size: 1em; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font style in Android 4.3-.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct background and color in IE 9-.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background-color: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` elements from affecting the line height in
|
||||
* all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
audio,
|
||||
video {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in iOS 4-7.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the border on images inside links in IE 10-.
|
||||
*/
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the overflow in IE.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* 1. Change the font styles in all browsers (opinionated).
|
||||
* 2. Remove the margin in Firefox and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: sans-serif; /* 1 */
|
||||
font-size: 100%; /* 1 */
|
||||
line-height: 1.15; /* 1 */
|
||||
margin: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the overflow in IE.
|
||||
* 1. Show the overflow in Edge.
|
||||
*/
|
||||
|
||||
button,
|
||||
input { /* 1 */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inheritance of text transform in Edge, Firefox, and IE.
|
||||
* 1. Remove the inheritance of text transform in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select { /* 1 */
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
|
||||
* controls in Android 4.
|
||||
* 2. Correct the inability to style clickable types in iOS and Safari.
|
||||
*/
|
||||
|
||||
button,
|
||||
html [type="button"], /* 1 */
|
||||
[type="reset"],
|
||||
[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner border and padding in Firefox.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
[type="button"]::-moz-focus-inner,
|
||||
[type="reset"]::-moz-focus-inner,
|
||||
[type="submit"]::-moz-focus-inner {
|
||||
border-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the focus styles unset by the previous rule.
|
||||
*/
|
||||
|
||||
button:-moz-focusring,
|
||||
[type="button"]:-moz-focusring,
|
||||
[type="reset"]:-moz-focusring,
|
||||
[type="submit"]:-moz-focusring {
|
||||
outline: 1px dotted ButtonText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the padding in Firefox.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
padding: 0.35em 0.75em 0.625em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the text wrapping in Edge and IE.
|
||||
* 2. Correct the color inheritance from `fieldset` elements in IE.
|
||||
* 3. Remove the padding so developers are not caught out when they zero out
|
||||
* `fieldset` elements in all browsers.
|
||||
*/
|
||||
|
||||
legend {
|
||||
box-sizing: border-box; /* 1 */
|
||||
color: inherit; /* 2 */
|
||||
display: table; /* 1 */
|
||||
max-width: 100%; /* 1 */
|
||||
padding: 0; /* 3 */
|
||||
white-space: normal; /* 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct display in IE 9-.
|
||||
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
progress {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the default vertical scrollbar in IE.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Add the correct box sizing in IE 10-.
|
||||
* 2. Remove the padding in IE 10-.
|
||||
*/
|
||||
|
||||
[type="checkbox"],
|
||||
[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the cursor style of increment and decrement buttons in Chrome.
|
||||
*/
|
||||
|
||||
[type="number"]::-webkit-inner-spin-button,
|
||||
[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the odd appearance in Chrome and Safari.
|
||||
* 2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
outline-offset: -2px; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
|
||||
*/
|
||||
|
||||
[type="search"]::-webkit-search-cancel-button,
|
||||
[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct the inability to style clickable types in iOS and Safari.
|
||||
* 2. Change font properties to `inherit` in Safari.
|
||||
*/
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
}
|
||||
|
||||
/* Interactive
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Add the correct display in IE 9-.
|
||||
* 1. Add the correct display in Edge, IE, and Firefox.
|
||||
*/
|
||||
|
||||
details, /* 1 */
|
||||
menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the correct display in all browsers.
|
||||
*/
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
}
|
||||
|
||||
/* Scripting
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 9-.
|
||||
*/
|
||||
|
||||
canvas {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the correct display in IE.
|
||||
*/
|
||||
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hidden
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Add the correct display in IE 10-.
|
||||
*/
|
||||
|
||||
[hidden] {
|
||||
display: none;
|
||||
}
|
||||
334
assets/static/sass/components/_preloader.scss
Normal file
334
assets/static/sass/components/_preloader.scss
Normal file
@@ -0,0 +1,334 @@
|
||||
/*
|
||||
@license
|
||||
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
||||
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
Code distributed by Google as part of the polymer project is also
|
||||
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
*/
|
||||
|
||||
/**************************/
|
||||
/* STYLES FOR THE SPINNER */
|
||||
/**************************/
|
||||
|
||||
/*
|
||||
* Constants:
|
||||
* STROKEWIDTH = 3px
|
||||
* ARCSIZE = 270 degrees (amount of circle the arc takes up)
|
||||
* ARCTIME = 1333ms (time it takes to expand and contract arc)
|
||||
* ARCSTARTROT = 216 degrees (how much the start location of the arc
|
||||
* should rotate each time, 216 gives us a
|
||||
* 5 pointed star shape (it's 360/5 * 3).
|
||||
* For a 7 pointed star, we might do
|
||||
* 360/7 * 3 = 154.286)
|
||||
* CONTAINERWIDTH = 28px
|
||||
* SHRINK_TIME = 400ms
|
||||
*/
|
||||
|
||||
|
||||
.preloader-wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
|
||||
&.small {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
&.big {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
&.active {
|
||||
/* duration: 360 * ARCTIME / (ARCSTARTROT + (360-ARCSIZE)) */
|
||||
-webkit-animation: container-rotate 1568ms linear infinite;
|
||||
animation: container-rotate 1568ms linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes container-rotate {
|
||||
to { -webkit-transform: rotate(360deg) }
|
||||
}
|
||||
|
||||
@keyframes container-rotate {
|
||||
to { transform: rotate(360deg) }
|
||||
}
|
||||
|
||||
.spinner-layer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
border-color: $spinner-default-color;
|
||||
}
|
||||
|
||||
.spinner-blue,
|
||||
.spinner-blue-only {
|
||||
border-color: #4285f4;
|
||||
}
|
||||
|
||||
.spinner-red,
|
||||
.spinner-red-only {
|
||||
border-color: #db4437;
|
||||
}
|
||||
|
||||
.spinner-yellow,
|
||||
.spinner-yellow-only {
|
||||
border-color: #f4b400;
|
||||
}
|
||||
|
||||
.spinner-green,
|
||||
.spinner-green-only {
|
||||
border-color: #0f9d58;
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORTANT NOTE ABOUT CSS ANIMATION PROPERTIES (keanulee):
|
||||
*
|
||||
* iOS Safari (tested on iOS 8.1) does not handle animation-delay very well - it doesn't
|
||||
* guarantee that the animation will start _exactly_ after that value. So we avoid using
|
||||
* animation-delay and instead set custom keyframes for each color (as redundant as it
|
||||
* seems).
|
||||
*
|
||||
* We write out each animation in full (instead of separating animation-name,
|
||||
* animation-duration, etc.) because under the polyfill, Safari does not recognize those
|
||||
* specific properties properly, treats them as -webkit-animation, and overrides the
|
||||
* other animation rules. See https://github.com/Polymer/platform/issues/53.
|
||||
*/
|
||||
.active .spinner-layer.spinner-blue {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, blue-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer.spinner-red {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, red-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer.spinner-yellow {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, yellow-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer.spinner-green {
|
||||
/* durations: 4 * ARCTIME */
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both, green-fade-in-out 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .spinner-layer,
|
||||
.active .spinner-layer.spinner-blue-only,
|
||||
.active .spinner-layer.spinner-red-only,
|
||||
.active .spinner-layer.spinner-yellow-only,
|
||||
.active .spinner-layer.spinner-green-only {
|
||||
/* durations: 4 * ARCTIME */
|
||||
opacity: 1;
|
||||
-webkit-animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: fill-unfill-rotate 5332ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fill-unfill-rotate {
|
||||
12.5% { -webkit-transform: rotate(135deg); } /* 0.5 * ARCSIZE */
|
||||
25% { -webkit-transform: rotate(270deg); } /* 1 * ARCSIZE */
|
||||
37.5% { -webkit-transform: rotate(405deg); } /* 1.5 * ARCSIZE */
|
||||
50% { -webkit-transform: rotate(540deg); } /* 2 * ARCSIZE */
|
||||
62.5% { -webkit-transform: rotate(675deg); } /* 2.5 * ARCSIZE */
|
||||
75% { -webkit-transform: rotate(810deg); } /* 3 * ARCSIZE */
|
||||
87.5% { -webkit-transform: rotate(945deg); } /* 3.5 * ARCSIZE */
|
||||
to { -webkit-transform: rotate(1080deg); } /* 4 * ARCSIZE */
|
||||
}
|
||||
|
||||
@keyframes fill-unfill-rotate {
|
||||
12.5% { transform: rotate(135deg); } /* 0.5 * ARCSIZE */
|
||||
25% { transform: rotate(270deg); } /* 1 * ARCSIZE */
|
||||
37.5% { transform: rotate(405deg); } /* 1.5 * ARCSIZE */
|
||||
50% { transform: rotate(540deg); } /* 2 * ARCSIZE */
|
||||
62.5% { transform: rotate(675deg); } /* 2.5 * ARCSIZE */
|
||||
75% { transform: rotate(810deg); } /* 3 * ARCSIZE */
|
||||
87.5% { transform: rotate(945deg); } /* 3.5 * ARCSIZE */
|
||||
to { transform: rotate(1080deg); } /* 4 * ARCSIZE */
|
||||
}
|
||||
|
||||
@-webkit-keyframes blue-fade-in-out {
|
||||
from { opacity: 1; }
|
||||
25% { opacity: 1; }
|
||||
26% { opacity: 0; }
|
||||
89% { opacity: 0; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes blue-fade-in-out {
|
||||
from { opacity: 1; }
|
||||
25% { opacity: 1; }
|
||||
26% { opacity: 0; }
|
||||
89% { opacity: 0; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes red-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
15% { opacity: 0; }
|
||||
25% { opacity: 1; }
|
||||
50% { opacity: 1; }
|
||||
51% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes red-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
15% { opacity: 0; }
|
||||
25% { opacity: 1; }
|
||||
50% { opacity: 1; }
|
||||
51% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes yellow-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
40% { opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
75% { opacity: 1; }
|
||||
76% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes yellow-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
40% { opacity: 0; }
|
||||
50% { opacity: 1; }
|
||||
75% { opacity: 1; }
|
||||
76% { opacity: 0; }
|
||||
}
|
||||
|
||||
@-webkit-keyframes green-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
65% { opacity: 0; }
|
||||
75% { opacity: 1; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes green-fade-in-out {
|
||||
from { opacity: 0; }
|
||||
65% { opacity: 0; }
|
||||
75% { opacity: 1; }
|
||||
90% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the gap that appear between the two adjacent div.circle-clipper while the
|
||||
* spinner is rotating (appears on Chrome 38, Safari 7.1, and IE 11).
|
||||
*/
|
||||
.gap-patch {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 45%;
|
||||
width: 10%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-color: inherit;
|
||||
}
|
||||
|
||||
.gap-patch .circle {
|
||||
width: 1000%;
|
||||
left: -450%;
|
||||
}
|
||||
|
||||
.circle-clipper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-color: inherit;
|
||||
|
||||
.circle {
|
||||
width: 200%;
|
||||
height: 100%;
|
||||
border-width: 3px; /* STROKEWIDTH */
|
||||
border-style: solid;
|
||||
border-color: inherit;
|
||||
border-bottom-color: transparent !important;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: none;
|
||||
animation: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&.left .circle {
|
||||
left: 0;
|
||||
border-right-color: transparent !important;
|
||||
-webkit-transform: rotate(129deg);
|
||||
transform: rotate(129deg);
|
||||
}
|
||||
&.right .circle {
|
||||
left: -100%;
|
||||
border-left-color: transparent !important;
|
||||
-webkit-transform: rotate(-129deg);
|
||||
transform: rotate(-129deg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.active .circle-clipper.left .circle {
|
||||
/* duration: ARCTIME */
|
||||
-webkit-animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: left-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
.active .circle-clipper.right .circle {
|
||||
/* duration: ARCTIME */
|
||||
-webkit-animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
animation: right-spin 1333ms cubic-bezier(0.4, 0.0, 0.2, 1) infinite both;
|
||||
}
|
||||
|
||||
@-webkit-keyframes left-spin {
|
||||
from { -webkit-transform: rotate(130deg); }
|
||||
50% { -webkit-transform: rotate(-5deg); }
|
||||
to { -webkit-transform: rotate(130deg); }
|
||||
}
|
||||
|
||||
@keyframes left-spin {
|
||||
from { transform: rotate(130deg); }
|
||||
50% { transform: rotate(-5deg); }
|
||||
to { transform: rotate(130deg); }
|
||||
}
|
||||
|
||||
@-webkit-keyframes right-spin {
|
||||
from { -webkit-transform: rotate(-130deg); }
|
||||
50% { -webkit-transform: rotate(5deg); }
|
||||
to { -webkit-transform: rotate(-130deg); }
|
||||
}
|
||||
|
||||
@keyframes right-spin {
|
||||
from { transform: rotate(-130deg); }
|
||||
50% { transform: rotate(5deg); }
|
||||
to { transform: rotate(-130deg); }
|
||||
}
|
||||
|
||||
#spinnerContainer.cooldown {
|
||||
/* duration: SHRINK_TIME */
|
||||
-webkit-animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
animation: container-rotate 1568ms linear infinite, fade-out 400ms cubic-bezier(0.4, 0.0, 0.2, 1);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade-out {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
|
||||
@keyframes fade-out {
|
||||
from { opacity: 1; }
|
||||
to { opacity: 0; }
|
||||
}
|
||||
34
assets/static/sass/components/_pulse.scss
Normal file
34
assets/static/sass/components/_pulse.scss
Normal file
@@ -0,0 +1,34 @@
|
||||
.pulse {
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: inherit;
|
||||
border-radius: inherit;
|
||||
transition: opacity .3s, transform .3s;
|
||||
animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@keyframes pulse-animation {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
}
|
||||
216
assets/static/sass/components/_sidenav.scss
Normal file
216
assets/static/sass/components/_sidenav.scss
Normal file
@@ -0,0 +1,216 @@
|
||||
.sidenav {
|
||||
position: fixed;
|
||||
width: $sidenav-width;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
transform: translateX(-100%);
|
||||
height: 100%;
|
||||
height: calc(100% + 60px);
|
||||
height: -moz-calc(100%); //Temporary Firefox Fix
|
||||
padding-bottom: 60px;
|
||||
background-color: $sidenav-bg-color;
|
||||
z-index: 999;
|
||||
overflow-y: auto;
|
||||
will-change: transform;
|
||||
backface-visibility: hidden;
|
||||
transform: translateX(-105%);
|
||||
|
||||
@extend .z-depth-1;
|
||||
|
||||
// Right Align
|
||||
&.right-aligned {
|
||||
right: 0;
|
||||
transform: translateX(105%);
|
||||
left: auto;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
.collapsible {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
li {
|
||||
float: none;
|
||||
line-height: $sidenav-line-height;
|
||||
|
||||
&.active { background-color: rgba(0,0,0,.05); }
|
||||
}
|
||||
|
||||
li > a {
|
||||
color: $sidenav-font-color;
|
||||
display: block;
|
||||
font-size: $sidenav-font-size;
|
||||
font-weight: 500;
|
||||
height: $sidenav-item-height;
|
||||
line-height: $sidenav-line-height;
|
||||
padding: 0 ($sidenav-padding * 2);
|
||||
|
||||
&:hover { background-color: rgba(0,0,0,.05);}
|
||||
|
||||
&.btn, &.btn-large, &.btn-flat, &.btn-floating {
|
||||
margin: 10px 15px;
|
||||
}
|
||||
|
||||
&.btn,
|
||||
&.btn-large,
|
||||
&.btn-floating { color: $button-raised-color; }
|
||||
&.btn-flat { color: $button-flat-color; }
|
||||
|
||||
&.btn:hover,
|
||||
&.btn-large:hover { background-color: lighten($button-raised-background, 5%); }
|
||||
&.btn-floating:hover { background-color: $button-raised-background; }
|
||||
|
||||
& > i,
|
||||
& > [class^="mdi-"], li > a > [class*="mdi-"],
|
||||
& > i.material-icons {
|
||||
float: left;
|
||||
height: $sidenav-item-height;
|
||||
line-height: $sidenav-line-height;
|
||||
margin: 0 ($sidenav-padding * 2) 0 0;
|
||||
width: $sidenav-item-height / 2;
|
||||
color: rgba(0,0,0,.54);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.divider {
|
||||
margin: ($sidenav-padding / 2) 0 0 0;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
cursor: initial;
|
||||
pointer-events: none;
|
||||
color: rgba(0,0,0,.54);
|
||||
font-size: $sidenav-font-size;
|
||||
font-weight: 500;
|
||||
line-height: $sidenav-line-height;
|
||||
}
|
||||
|
||||
.user-view {
|
||||
position: relative;
|
||||
padding: ($sidenav-padding * 2) ($sidenav-padding * 2) 0;
|
||||
margin-bottom: $sidenav-padding / 2;
|
||||
|
||||
& > a {
|
||||
&:hover { background-color: transparent; }
|
||||
height: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.background {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.circle, .name, .email {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.circle {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
|
||||
.name,
|
||||
.email {
|
||||
font-size: $sidenav-font-size;
|
||||
line-height: $sidenav-line-height / 2;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-top: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.email {
|
||||
padding-bottom: 16px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Touch interaction
|
||||
.drag-target {
|
||||
// Right Align
|
||||
&.right-aligned {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
height: 100%;
|
||||
width: 10px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
|
||||
// Fixed Sidenav shown
|
||||
.sidenav.sidenav-fixed {
|
||||
// Right Align
|
||||
&.right-aligned {
|
||||
right: 0;
|
||||
left: auto;
|
||||
}
|
||||
|
||||
left: 0;
|
||||
transform: translateX(0);
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
// Fixed Sidenav hide on smaller
|
||||
@media #{$medium-and-down} {
|
||||
.sidenav {
|
||||
&.sidenav-fixed {
|
||||
transform: translateX(-105%);
|
||||
|
||||
&.right-aligned {
|
||||
transform: translateX(105%);
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
padding: 0 $sidenav-padding;
|
||||
}
|
||||
|
||||
.user-view {
|
||||
padding: $sidenav-padding $sidenav-padding 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.sidenav .collapsible-body > ul:not(.collapsible) > li.active,
|
||||
.sidenav.sidenav-fixed .collapsible-body > ul:not(.collapsible) > li.active {
|
||||
background-color: $primary-color;
|
||||
a {
|
||||
color: $sidenav-bg-color;
|
||||
}
|
||||
}
|
||||
.sidenav .collapsible-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.sidenav-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
height: 120vh;
|
||||
background-color: rgba(0,0,0,.5);
|
||||
z-index: 997;
|
||||
display: none;
|
||||
}
|
||||
92
assets/static/sass/components/_slider.scss
Normal file
92
assets/static/sass/components/_slider.scss
Normal file
@@ -0,0 +1,92 @@
|
||||
.slider {
|
||||
position: relative;
|
||||
height: 400px;
|
||||
width: 100%;
|
||||
|
||||
// Fullscreen slider
|
||||
&.fullscreen {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
ul.slides {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
ul.indicators {
|
||||
z-index: 2;
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.slides {
|
||||
background-color: $slider-bg-color;
|
||||
margin: 0;
|
||||
height: 400px;
|
||||
|
||||
li {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.caption {
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 15%;
|
||||
left: 15%;
|
||||
width: 70%;
|
||||
opacity: 0;
|
||||
|
||||
p { color: $slider-bg-color-light; }
|
||||
}
|
||||
|
||||
&.active {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.indicators {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
|
||||
.indicator-item {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin: 0 12px;
|
||||
background-color: $slider-bg-color-light;
|
||||
|
||||
transition: background-color .3s;
|
||||
border-radius: 50%;
|
||||
|
||||
&.active {
|
||||
background-color: $slider-indicator-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
33
assets/static/sass/components/_table_of_contents.scss
Normal file
33
assets/static/sass/components/_table_of_contents.scss
Normal file
@@ -0,0 +1,33 @@
|
||||
/***************
|
||||
Nav List
|
||||
***************/
|
||||
.table-of-contents {
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 2px 0;
|
||||
}
|
||||
a {
|
||||
display: inline-block;
|
||||
font-weight: 300;
|
||||
color: #757575;
|
||||
padding-left: 16px;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
letter-spacing: .4;
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
color: lighten(#757575, 20%);
|
||||
padding-left: 15px;
|
||||
border-left: 1px solid $primary-color;
|
||||
}
|
||||
&.active {
|
||||
font-weight: 500;
|
||||
padding-left: 14px;
|
||||
border-left: 2px solid $primary-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
99
assets/static/sass/components/_tabs.scss
Normal file
99
assets/static/sass/components/_tabs.scss
Normal file
@@ -0,0 +1,99 @@
|
||||
.tabs {
|
||||
&.tabs-transparent {
|
||||
background-color: transparent;
|
||||
|
||||
.tab a,
|
||||
.tab.disabled a,
|
||||
.tab.disabled a:hover {
|
||||
color: rgba(255,255,255,0.7);
|
||||
}
|
||||
|
||||
.tab a:hover,
|
||||
.tab a.active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&.tabs-fixed-width {
|
||||
display: flex;
|
||||
|
||||
.tab {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
position: relative;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
height: 48px;
|
||||
width: 100%;
|
||||
background-color: $tabs-bg-color;
|
||||
margin: 0 auto;
|
||||
white-space: nowrap;
|
||||
|
||||
.tab {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
line-height: 48px;
|
||||
height: 48px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-transform: uppercase;
|
||||
|
||||
a {
|
||||
&:focus,
|
||||
&:focus.active {
|
||||
background-color: transparentize($tabs-underline-color, .8);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: transparent;
|
||||
color: $tabs-text-color;
|
||||
}
|
||||
|
||||
color: rgba($tabs-text-color, .7);
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 24px;
|
||||
font-size: 14px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
transition: color .28s ease, background-color .28s ease;
|
||||
}
|
||||
|
||||
&.disabled a,
|
||||
&.disabled a:hover {
|
||||
color: rgba($tabs-text-color, .4);
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
.indicator {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
height: 2px;
|
||||
background-color: $tabs-underline-color;
|
||||
will-change: left, right;
|
||||
}
|
||||
}
|
||||
|
||||
// Fixed Sidenav hide on smaller
|
||||
@media #{$medium-and-down} {
|
||||
.tabs {
|
||||
display: flex;
|
||||
|
||||
.tab {
|
||||
flex-grow: 1;
|
||||
|
||||
a {
|
||||
padding: 0 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
103
assets/static/sass/components/_tapTarget.scss
Normal file
103
assets/static/sass/components/_tapTarget.scss
Normal file
@@ -0,0 +1,103 @@
|
||||
.tap-target-wrapper {
|
||||
width: 800px;
|
||||
height: 800px;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
visibility: hidden;
|
||||
transition: visibility 0s .3s;
|
||||
}
|
||||
|
||||
.tap-target-wrapper.open {
|
||||
visibility: visible;
|
||||
transition: visibility 0s;
|
||||
|
||||
.tap-target {
|
||||
transform: scale(1);
|
||||
opacity: .95;
|
||||
transition:
|
||||
transform .3s cubic-bezier(.42,0,.58,1),
|
||||
opacity .3s cubic-bezier(.42,0,.58,1);
|
||||
}
|
||||
|
||||
.tap-target-wave::before {
|
||||
transform: scale(1);
|
||||
}
|
||||
.tap-target-wave::after {
|
||||
visibility: visible;
|
||||
animation: pulse-animation 1s cubic-bezier(0.24, 0, 0.38, 1) infinite;
|
||||
transition:
|
||||
opacity .3s,
|
||||
transform .3s,
|
||||
visibility 0s 1s;
|
||||
}
|
||||
}
|
||||
|
||||
.tap-target {
|
||||
position: absolute;
|
||||
font-size: 1rem;
|
||||
border-radius: 50%;
|
||||
background-color: $primary-color;
|
||||
box-shadow: 0 20px 20px 0 rgba(0,0,0,0.14), 0 10px 50px 0 rgba(0,0,0,0.12), 0 30px 10px -20px rgba(0,0,0,0.2);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
transition:
|
||||
transform .3s cubic-bezier(.42,0,.58,1),
|
||||
opacity .3s cubic-bezier(.42,0,.58,1);
|
||||
}
|
||||
|
||||
.tap-target-content {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.tap-target-wave {
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
&::before {
|
||||
transform: scale(0);
|
||||
transition: transform .3s;
|
||||
}
|
||||
&::after {
|
||||
visibility: hidden;
|
||||
transition:
|
||||
opacity .3s,
|
||||
transform .3s,
|
||||
visibility 0s;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.tap-target-origin {
|
||||
&:not(.btn),
|
||||
&:not(.btn):hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
|
||||
z-index: 10002;
|
||||
position: absolute !important;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
.tap-target, .tap-target-wrapper {
|
||||
width: 600px;
|
||||
height: 600px;
|
||||
}
|
||||
}
|
||||
183
assets/static/sass/components/_timepicker.scss
Normal file
183
assets/static/sass/components/_timepicker.scss
Normal file
@@ -0,0 +1,183 @@
|
||||
/* Timepicker Containers */
|
||||
.timepicker-modal {
|
||||
max-width: 325px;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.timepicker-container.modal-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Clock Digital Display */
|
||||
.timepicker-digital-display {
|
||||
flex: 1 auto;
|
||||
background-color: $secondary-color;
|
||||
padding: 10px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.timepicker-text-container {
|
||||
font-size: 4rem;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.timepicker-span-hours,
|
||||
.timepicker-span-minutes,
|
||||
.timepicker-span-am-pm div {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.timepicker-span-hours {
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.timepicker-span-minutes {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.timepicker-display-am-pm {
|
||||
font-size: 1.3rem;
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
bottom: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
/* Analog Clock Display */
|
||||
.timepicker-analog-display {
|
||||
flex: 2.5 auto;
|
||||
}
|
||||
|
||||
.timepicker-plate {
|
||||
background-color: $timepicker-clock-plate-bg;
|
||||
border-radius: 50%;
|
||||
width: 270px;
|
||||
height: 270px;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
margin: auto;
|
||||
margin-top: 25px;
|
||||
margin-bottom: 5px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.timepicker-canvas,
|
||||
.timepicker-dial {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.timepicker-minutes {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.timepicker-tick {
|
||||
border-radius: 50%;
|
||||
color: $timepicker-clock-color;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.timepicker-tick.active,
|
||||
.timepicker-tick:hover {
|
||||
background-color: transparentize($secondary-color, .75);
|
||||
}
|
||||
.timepicker-dial {
|
||||
transition: transform 350ms, opacity 350ms;
|
||||
}
|
||||
.timepicker-dial-out {
|
||||
&.timepicker-hours {
|
||||
transform: scale(1.1, 1.1);
|
||||
}
|
||||
|
||||
&.timepicker-minutes {
|
||||
transform: scale(.8, .8);
|
||||
}
|
||||
|
||||
opacity: 0;
|
||||
}
|
||||
.timepicker-canvas {
|
||||
transition: opacity 175ms;
|
||||
|
||||
line {
|
||||
stroke: $secondary-color;
|
||||
stroke-width: 4;
|
||||
stroke-linecap: round;
|
||||
}
|
||||
}
|
||||
.timepicker-canvas-out {
|
||||
opacity: 0.25;
|
||||
}
|
||||
.timepicker-canvas-bearing {
|
||||
stroke: none;
|
||||
fill: $secondary-color;
|
||||
}
|
||||
.timepicker-canvas-bg {
|
||||
stroke: none;
|
||||
fill: $secondary-color;
|
||||
}
|
||||
|
||||
|
||||
/* Footer */
|
||||
.timepicker-footer {
|
||||
margin: 0 auto;
|
||||
padding: 5px 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.timepicker-clear {
|
||||
color: $error-color;
|
||||
}
|
||||
|
||||
.timepicker-close {
|
||||
color: $secondary-color;
|
||||
}
|
||||
|
||||
.timepicker-clear,
|
||||
.timepicker-close {
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
/* Media Queries */
|
||||
@media #{$medium-and-up} {
|
||||
.timepicker-modal {
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.timepicker-container.modal-content {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.timepicker-text-container {
|
||||
top: 32%;
|
||||
}
|
||||
|
||||
.timepicker-display-am-pm {
|
||||
position: relative;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
text-align: center;
|
||||
margin-top: 1.2rem;
|
||||
}
|
||||
}
|
||||
58
assets/static/sass/components/_toast.scss
Normal file
58
assets/static/sass/components/_toast.scss
Normal file
@@ -0,0 +1,58 @@
|
||||
#toast-container {
|
||||
display:block;
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
|
||||
@media #{$small-and-down} {
|
||||
min-width: 100%;
|
||||
bottom: 0%;
|
||||
}
|
||||
@media #{$medium-only} {
|
||||
left: 5%;
|
||||
bottom: 7%;
|
||||
max-width: 90%;
|
||||
}
|
||||
@media #{$large-and-up} {
|
||||
top: 10%;
|
||||
right: 7%;
|
||||
max-width: 86%;
|
||||
}
|
||||
}
|
||||
|
||||
.toast {
|
||||
@extend .z-depth-1;
|
||||
border-radius: 2px;
|
||||
top: 35px;
|
||||
width: auto;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
max-width:100%;
|
||||
height: auto;
|
||||
min-height: $toast-height;
|
||||
line-height: 1.5em;
|
||||
background-color: $toast-color;
|
||||
padding: 10px 25px;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 300;
|
||||
color: $toast-text-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
cursor: default;
|
||||
|
||||
.toast-action {
|
||||
color: $toast-action-color;
|
||||
font-weight: 500;
|
||||
margin-right: -25px;
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
&.rounded{
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
@media #{$small-and-down} {
|
||||
width: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
32
assets/static/sass/components/_tooltip.scss
Normal file
32
assets/static/sass/components/_tooltip.scss
Normal file
@@ -0,0 +1,32 @@
|
||||
.material-tooltip {
|
||||
padding: 10px 8px;
|
||||
font-size: 1rem;
|
||||
z-index: 2000;
|
||||
background-color: transparent;
|
||||
border-radius: 2px;
|
||||
color: #fff;
|
||||
min-height: 36px;
|
||||
line-height: 120%;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
max-width: calc(100% - 4px);
|
||||
overflow: hidden;
|
||||
left: 0;
|
||||
top: 0;
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
background-color: #323232;
|
||||
}
|
||||
|
||||
.backdrop {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
height: 7px;
|
||||
width: 14px;
|
||||
border-radius: 0 0 50% 50%;
|
||||
background-color: #323232;
|
||||
z-index: -1;
|
||||
transform-origin: 50% 0%;
|
||||
visibility: hidden;
|
||||
}
|
||||
13
assets/static/sass/components/_transitions.scss
Normal file
13
assets/static/sass/components/_transitions.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
// Scale transition
|
||||
.scale-transition {
|
||||
&.scale-out {
|
||||
transform: scale(0);
|
||||
transition: transform .2s !important;
|
||||
}
|
||||
|
||||
&.scale-in {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
transition: transform .3s cubic-bezier(0.53, 0.01, 0.36, 1.63) !important;
|
||||
}
|
||||
60
assets/static/sass/components/_typography.scss
Normal file
60
assets/static/sass/components/_typography.scss
Normal file
@@ -0,0 +1,60 @@
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
html{
|
||||
line-height: 1.5;
|
||||
|
||||
@media only screen and (min-width: 0) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: $medium-screen) {
|
||||
font-size: 14.5px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: $large-screen) {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
font-family: $font-stack;
|
||||
font-weight: normal;
|
||||
color: $off-black;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: 400;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
// Header Styles
|
||||
h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; }
|
||||
h1 { font-size: $h1-fontsize; line-height: 110%; margin: ($h1-fontsize / 1.5) 0 ($h1-fontsize / 2.5) 0;}
|
||||
h2 { font-size: $h2-fontsize; line-height: 110%; margin: ($h2-fontsize / 1.5) 0 ($h2-fontsize / 2.5) 0;}
|
||||
h3 { font-size: $h3-fontsize; line-height: 110%; margin: ($h3-fontsize / 1.5) 0 ($h3-fontsize / 2.5) 0;}
|
||||
h4 { font-size: $h4-fontsize; line-height: 110%; margin: ($h4-fontsize / 1.5) 0 ($h4-fontsize / 2.5) 0;}
|
||||
h5 { font-size: $h5-fontsize; line-height: 110%; margin: ($h5-fontsize / 1.5) 0 ($h5-fontsize / 2.5) 0;}
|
||||
h6 { font-size: $h6-fontsize; line-height: 110%; margin: ($h6-fontsize / 1.5) 0 ($h6-fontsize / 2.5) 0;}
|
||||
|
||||
// Text Styles
|
||||
em { font-style: italic; }
|
||||
strong { font-weight: 500; }
|
||||
small { font-size: 75%; }
|
||||
.light { font-weight: 300; }
|
||||
.thin { font-weight: 200; }
|
||||
|
||||
|
||||
.flow-text{
|
||||
$i: 0;
|
||||
@while $i <= $intervals {
|
||||
@media only screen and (min-width : 360 + ($i * $interval-size)) {
|
||||
font-size: 1.2rem * (1 + (.02 * $i));
|
||||
}
|
||||
$i: $i + 1;
|
||||
}
|
||||
|
||||
// Handle below 360px screen
|
||||
@media only screen and (max-width: 360px) {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
}
|
||||
349
assets/static/sass/components/_variables.scss
Normal file
349
assets/static/sass/components/_variables.scss
Normal file
@@ -0,0 +1,349 @@
|
||||
// ==========================================================================
|
||||
// Materialize variables
|
||||
// ==========================================================================
|
||||
//
|
||||
// Table of Contents:
|
||||
//
|
||||
// 1. Colors
|
||||
// 2. Badges
|
||||
// 3. Buttons
|
||||
// 4. Cards
|
||||
// 5. Carousel
|
||||
// 6. Collapsible
|
||||
// 7. Chips
|
||||
// 8. Date + Time Picker
|
||||
// 9. Dropdown
|
||||
// 10. Forms
|
||||
// 11. Global
|
||||
// 12. Grid
|
||||
// 13. Navigation Bar
|
||||
// 14. Side Navigation
|
||||
// 15. Photo Slider
|
||||
// 16. Spinners | Loaders
|
||||
// 17. Tabs
|
||||
// 18. Tables
|
||||
// 19. Toasts
|
||||
// 20. Typography
|
||||
// 21. Footer
|
||||
// 22. Flow Text
|
||||
// 23. Collections
|
||||
// 24. Progress Bar
|
||||
|
||||
|
||||
|
||||
// 1. Colors
|
||||
// ==========================================================================
|
||||
|
||||
$primary-color: color("grey", "darken-4") !default;
|
||||
$primary-color-light: lighten($primary-color, 15%) !default;
|
||||
$primary-color-dark: darken($primary-color, 15%) !default;
|
||||
|
||||
$secondary-color: color("blue", "darken-4") !default;
|
||||
$success-color: color("green", "base") !default;
|
||||
$error-color: color("red", "base") !default;
|
||||
$link-color: color("light-blue", "darken-1") !default;
|
||||
|
||||
|
||||
// 2. Badges
|
||||
// ==========================================================================
|
||||
|
||||
$badge-bg-color: $secondary-color !default;
|
||||
$badge-height: 22px !default;
|
||||
|
||||
|
||||
// 3. Buttons
|
||||
// ==========================================================================
|
||||
|
||||
// Shared styles
|
||||
$button-border: none !default;
|
||||
$button-background-focus: lighten($secondary-color, 4%) !default;
|
||||
$button-font-size: 14px !default;
|
||||
$button-icon-font-size: 1.3rem !default;
|
||||
$button-height: 36px !default;
|
||||
$button-padding: 0 16px !default;
|
||||
$button-radius: 2px !default;
|
||||
|
||||
// Disabled styles
|
||||
$button-disabled-background: #DFDFDF !default;
|
||||
$button-disabled-color: #9F9F9F !default;
|
||||
|
||||
// Raised buttons
|
||||
$button-raised-background: $secondary-color !default;
|
||||
$button-raised-background-hover: lighten($button-raised-background, 5%) !default;
|
||||
$button-raised-color: #fff !default;
|
||||
|
||||
// Large buttons
|
||||
$button-large-font-size: 15px !default;
|
||||
$button-large-icon-font-size: 1.6rem !default;
|
||||
$button-large-height: $button-height * 1.5 !default;
|
||||
$button-floating-large-size: 56px !default;
|
||||
|
||||
// Small buttons
|
||||
$button-small-font-size: 13px !default;
|
||||
$button-small-icon-font-size: 1.2rem !default;
|
||||
$button-small-height: $button-height * .9 !default;
|
||||
$button-floating-small-size: $button-height * .9 !default;
|
||||
|
||||
// Flat buttons
|
||||
$button-flat-color: #343434 !default;
|
||||
$button-flat-disabled-color: lighten(#999, 10%) !default;
|
||||
|
||||
// Floating buttons
|
||||
$button-floating-background: $secondary-color !default;
|
||||
$button-floating-background-hover: $button-floating-background !default;
|
||||
$button-floating-color: #fff !default;
|
||||
$button-floating-size: 40px !default;
|
||||
$button-floating-radius: 50% !default;
|
||||
|
||||
|
||||
// 4. Cards
|
||||
// ==========================================================================
|
||||
|
||||
$card-padding: 24px !default;
|
||||
$card-bg-color: #fff !default;
|
||||
$card-link-color: color("orange", "accent-2") !default;
|
||||
$card-link-color-light: lighten($card-link-color, 20%) !default;
|
||||
|
||||
|
||||
// 5. Carousel
|
||||
// ==========================================================================
|
||||
|
||||
$carousel-height: 400px !default;
|
||||
$carousel-item-height: $carousel-height / 2 !default;
|
||||
$carousel-item-width: $carousel-item-height !default;
|
||||
|
||||
|
||||
// 6. Collapsible
|
||||
// ==========================================================================
|
||||
|
||||
$collapsible-height: 3rem !default;
|
||||
$collapsible-line-height: $collapsible-height !default;
|
||||
$collapsible-header-color: #fff !default;
|
||||
$collapsible-border-color: #ddd !default;
|
||||
|
||||
|
||||
// 7. Chips
|
||||
// ==========================================================================
|
||||
|
||||
$chip-bg-color: #e4e4e4 !default;
|
||||
$chip-border-color: #9e9e9e !default;
|
||||
$chip-selected-color: #26a69a !default;
|
||||
$chip-margin: 5px !default;
|
||||
|
||||
|
||||
// 8. Date + Time Picker
|
||||
// ==========================================================================
|
||||
|
||||
$datepicker-display-font-size: 2.8rem;
|
||||
$datepicker-calendar-header-color: #999;
|
||||
$datepicker-weekday-color: rgba(0, 0, 0, .87) !default;
|
||||
$datepicker-weekday-bg: darken($secondary-color, 7%) !default;
|
||||
$datepicker-date-bg: $secondary-color !default;
|
||||
$datepicker-year: rgba(255, 255, 255, .7) !default;
|
||||
$datepicker-focus: rgba(0,0,0, .05) !default;
|
||||
$datepicker-selected: $secondary-color !default;
|
||||
$datepicker-selected-outfocus: desaturate(lighten($secondary-color, 35%), 15%) !default;
|
||||
$datepicker-day-focus: transparentize(desaturate($secondary-color, 5%), .75) !default;
|
||||
$datepicker-disabled-day-color: rgba(0, 0, 0, .3) !default;
|
||||
|
||||
$timepicker-clock-color: rgba(0, 0, 0, .87) !default;
|
||||
$timepicker-clock-plate-bg: #eee !default;
|
||||
|
||||
|
||||
// 9. Dropdown
|
||||
// ==========================================================================
|
||||
|
||||
$dropdown-bg-color: #fff !default;
|
||||
$dropdown-hover-bg-color: #eee !default;
|
||||
$dropdown-color: $secondary-color !default;
|
||||
$dropdown-item-height: 50px !default;
|
||||
|
||||
|
||||
// 10. Forms
|
||||
// ==========================================================================
|
||||
|
||||
// Text Inputs + Textarea
|
||||
$input-height: 3rem !default;
|
||||
$input-border-color: color("grey", "base") !default;
|
||||
$input-border: 1px solid $input-border-color !default;
|
||||
$input-background: #fff !default;
|
||||
$input-error-color: $error-color !default;
|
||||
$input-success-color: $success-color !default;
|
||||
$input-focus-color: $secondary-color !default;
|
||||
$input-font-size: 16px !default;
|
||||
$input-margin-bottom: 8px;
|
||||
$input-margin: 0 0 $input-margin-bottom 0 !default;
|
||||
$input-padding: 0 !default;
|
||||
$label-font-size: .8rem !default;
|
||||
$input-disabled-color: rgba(0,0,0, .42) !default;
|
||||
$input-disabled-solid-color: #949494 !default;
|
||||
$input-disabled-border: 1px dotted $input-disabled-color !default;
|
||||
$input-invalid-border: 1px solid $input-error-color !default;
|
||||
$input-icon-size: 2rem;
|
||||
$placeholder-text-color: lighten($input-border-color, 20%) !default;
|
||||
|
||||
// Radio Buttons
|
||||
$radio-fill-color: $secondary-color !default;
|
||||
$radio-empty-color: #5a5a5a !default;
|
||||
$radio-border: 2px solid $radio-fill-color !default;
|
||||
|
||||
// Range
|
||||
$range-height: 14px !default;
|
||||
$range-width: 14px !default;
|
||||
$track-height: 3px !default;
|
||||
|
||||
// Select
|
||||
$select-border: 1px solid #f2f2f2 !default;
|
||||
$select-background: rgba(255, 255, 255, 0.90) !default;
|
||||
$select-focus: 1px solid lighten($secondary-color, 47%) !default;
|
||||
$select-option-hover: rgba(0,0,0,.08) !default;
|
||||
$select-option-focus: rgba(0,0,0,.08) !default;
|
||||
$select-option-selected: rgba(0,0,0,.03) !default;
|
||||
$select-padding: 5px !default;
|
||||
$select-radius: 2px !default;
|
||||
$select-disabled-color: rgba(0,0,0,.3) !default;
|
||||
|
||||
// Switches
|
||||
$switch-bg-color: $secondary-color !default;
|
||||
$switch-checked-lever-bg: desaturate(lighten($switch-bg-color, 25%), 25%) !default;
|
||||
$switch-unchecked-bg: #F1F1F1 !default;
|
||||
$switch-unchecked-lever-bg: rgba(0,0,0,.38) !default;
|
||||
$switch-radius: 15px !default;
|
||||
|
||||
|
||||
// 11. Global
|
||||
// ==========================================================================
|
||||
|
||||
// Media Query Ranges
|
||||
$small-screen-up: 601px !default;
|
||||
$medium-screen-up: 993px !default;
|
||||
$large-screen-up: 1201px !default;
|
||||
$small-screen: 600px !default;
|
||||
$medium-screen: 992px !default;
|
||||
$large-screen: 1200px !default;
|
||||
|
||||
$medium-and-up: "only screen and (min-width : #{$small-screen-up})" !default;
|
||||
$large-and-up: "only screen and (min-width : #{$medium-screen-up})" !default;
|
||||
$extra-large-and-up: "only screen and (min-width : #{$large-screen-up})" !default;
|
||||
$small-and-down: "only screen and (max-width : #{$small-screen})" !default;
|
||||
$medium-and-down: "only screen and (max-width : #{$medium-screen})" !default;
|
||||
$medium-only: "only screen and (min-width : #{$small-screen-up}) and (max-width : #{$medium-screen})" !default;
|
||||
|
||||
|
||||
// 12. Grid
|
||||
// ==========================================================================
|
||||
|
||||
$num-cols: 12 !default;
|
||||
$gutter-width: 1.5rem !default;
|
||||
$element-top-margin: $gutter-width/3 !default;
|
||||
$element-bottom-margin: ($gutter-width*2)/3 !default;
|
||||
|
||||
|
||||
// 13. Navigation Bar
|
||||
// ==========================================================================
|
||||
|
||||
$navbar-height: 64px !default;
|
||||
$navbar-line-height: $navbar-height !default;
|
||||
$navbar-height-mobile: 56px !default;
|
||||
$navbar-line-height-mobile: $navbar-height-mobile !default;
|
||||
$navbar-font-size: 1rem !default;
|
||||
$navbar-font-color: #fff !default;
|
||||
$navbar-brand-font-size: 2.1rem !default;
|
||||
|
||||
// 14. Side Navigation
|
||||
// ==========================================================================
|
||||
|
||||
$sidenav-width: 300px !default;
|
||||
$sidenav-font-size: 14px !default;
|
||||
$sidenav-font-color: rgba(0,0,0,.87) !default;
|
||||
$sidenav-bg-color: #fff !default;
|
||||
$sidenav-padding: 16px !default;
|
||||
$sidenav-item-height: 48px !default;
|
||||
$sidenav-line-height: $sidenav-item-height !default;
|
||||
|
||||
|
||||
// 15. Photo Slider
|
||||
// ==========================================================================
|
||||
|
||||
$slider-bg-color: color('grey', 'base') !default;
|
||||
$slider-bg-color-light: color('grey', 'lighten-2') !default;
|
||||
$slider-indicator-color: color('green', 'base') !default;
|
||||
|
||||
|
||||
// 16. Spinners | Loaders
|
||||
// ==========================================================================
|
||||
|
||||
$spinner-default-color: $secondary-color !default;
|
||||
|
||||
|
||||
// 17. Tabs
|
||||
// ==========================================================================
|
||||
|
||||
$tabs-underline-color: $primary-color-light !default;
|
||||
$tabs-text-color: $primary-color !default;
|
||||
$tabs-bg-color: #fff !default;
|
||||
|
||||
|
||||
// 18. Tables
|
||||
// ==========================================================================
|
||||
|
||||
$table-border-color: rgba(0,0,0,.12) !default;
|
||||
$table-striped-color: rgba(242, 242, 242, 0.5) !default;
|
||||
|
||||
|
||||
// 19. Toasts
|
||||
// ==========================================================================
|
||||
|
||||
$toast-height: 48px !default;
|
||||
$toast-color: #323232 !default;
|
||||
$toast-text-color: #fff !default;
|
||||
$toast-action-color: #eeff41;
|
||||
|
||||
|
||||
// 20. Typography
|
||||
// ==========================================================================
|
||||
|
||||
$font-stack: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !default;
|
||||
$off-black: rgba(0, 0, 0, 0.87) !default;
|
||||
// Header Styles
|
||||
$h1-fontsize: 4.2rem !default;
|
||||
$h2-fontsize: 3.56rem !default;
|
||||
$h3-fontsize: 2.92rem !default;
|
||||
$h4-fontsize: 2.28rem !default;
|
||||
$h5-fontsize: 1.64rem !default;
|
||||
$h6-fontsize: 1.15rem !default;
|
||||
|
||||
|
||||
// 21. Footer
|
||||
// ==========================================================================
|
||||
|
||||
$footer-font-color: #fff !default;
|
||||
$footer-bg-color: $primary-color !default;
|
||||
$footer-copyright-font-color: rgba(255,255,255,.8) !default;
|
||||
$footer-copyright-bg-color: rgba(51,51,51,.08) !default;
|
||||
|
||||
|
||||
// 22. Flow Text
|
||||
// ==========================================================================
|
||||
|
||||
$range : $large-screen - $small-screen !default;
|
||||
$intervals: 20 !default;
|
||||
$interval-size: $range / $intervals !default;
|
||||
|
||||
|
||||
// 23. Collections
|
||||
// ==========================================================================
|
||||
|
||||
$collection-border-color: #e0e0e0 !default;
|
||||
$collection-bg-color: #fff !default;
|
||||
$collection-active-bg-color: $secondary-color !default;
|
||||
$collection-active-color: lighten($secondary-color, 55%) !default;
|
||||
$collection-hover-bg-color: #ddd !default;
|
||||
$collection-link-color: $secondary-color !default;
|
||||
$collection-line-height: 1.5rem !default;
|
||||
|
||||
|
||||
// 24. Progress Bar
|
||||
// ==========================================================================
|
||||
|
||||
$progress-bar-color: $secondary-color !default;
|
||||
114
assets/static/sass/components/_waves.scss
Normal file
114
assets/static/sass/components/_waves.scss
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
/*!
|
||||
* Waves v0.6.0
|
||||
* http://fian.my.id/Waves
|
||||
*
|
||||
* Copyright 2014 Alfiana E. Sibuea and other contributors
|
||||
* Released under the MIT license
|
||||
* https://github.com/fians/Waves/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
|
||||
.waves-effect {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
vertical-align: middle;
|
||||
z-index: 1;
|
||||
transition: .3s ease-out;
|
||||
|
||||
.waves-ripple {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-top:-10px;
|
||||
margin-left:-10px;
|
||||
opacity: 0;
|
||||
|
||||
background: rgba(0,0,0,0.2);
|
||||
transition: all 0.7s ease-out;
|
||||
transition-property: transform, opacity;
|
||||
transform: scale(0);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Waves Colors
|
||||
&.waves-light .waves-ripple {
|
||||
background-color: rgba(255, 255, 255, 0.45);
|
||||
}
|
||||
&.waves-red .waves-ripple {
|
||||
background-color: rgba(244, 67, 54, .70);
|
||||
}
|
||||
&.waves-yellow .waves-ripple {
|
||||
background-color: rgba(255, 235, 59, .70);
|
||||
}
|
||||
&.waves-orange .waves-ripple {
|
||||
background-color: rgba(255, 152, 0, .70);
|
||||
}
|
||||
&.waves-purple .waves-ripple {
|
||||
background-color: rgba(156, 39, 176, 0.70);
|
||||
}
|
||||
&.waves-green .waves-ripple {
|
||||
background-color: rgba(76, 175, 80, 0.70);
|
||||
}
|
||||
&.waves-teal .waves-ripple {
|
||||
background-color: rgba(0, 150, 136, 0.70);
|
||||
}
|
||||
|
||||
// Style input button bug.
|
||||
input[type="button"], input[type="reset"], input[type="submit"] {
|
||||
border: 0;
|
||||
font-style: normal;
|
||||
font-size: inherit;
|
||||
text-transform: inherit;
|
||||
background: none;
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
.waves-notransition {
|
||||
transition: none #{"!important"};
|
||||
}
|
||||
|
||||
.waves-circle {
|
||||
transform: translateZ(0);
|
||||
-webkit-mask-image: -webkit-radial-gradient(circle, white 100%, black 100%);
|
||||
}
|
||||
|
||||
.waves-input-wrapper {
|
||||
border-radius: 0.2em;
|
||||
vertical-align: bottom;
|
||||
|
||||
.waves-button-input {
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.waves-circle {
|
||||
text-align: center;
|
||||
width: 2.5em;
|
||||
height: 2.5em;
|
||||
line-height: 2.5em;
|
||||
border-radius: 50%;
|
||||
-webkit-mask-image: none;
|
||||
}
|
||||
|
||||
.waves-block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Firefox Bug: link not triggered */
|
||||
.waves-effect .waves-ripple {
|
||||
z-index: -1;
|
||||
}
|
||||
200
assets/static/sass/components/forms/_checkboxes.scss
Normal file
200
assets/static/sass/components/forms/_checkboxes.scss
Normal file
@@ -0,0 +1,200 @@
|
||||
/* Checkboxes
|
||||
========================================================================== */
|
||||
|
||||
/* Remove default checkbox */
|
||||
[type="checkbox"]:not(:checked),
|
||||
[type="checkbox"]:checked {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Checkbox Styles
|
||||
[type="checkbox"] {
|
||||
// Text Label Style
|
||||
+ span:not(.lever) {
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 1rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
/* checkbox aspect */
|
||||
+ span:not(.lever):before,
|
||||
&:not(.filled-in) + span:not(.lever):after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
z-index: 0;
|
||||
border: 2px solid $radio-empty-color;
|
||||
border-radius: 1px;
|
||||
margin-top: 3px;
|
||||
transition: .2s;
|
||||
}
|
||||
|
||||
&:not(.filled-in) + span:not(.lever):after {
|
||||
border: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
&:not(:checked):disabled + span:not(.lever):before {
|
||||
border: none;
|
||||
background-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
// Focused styles
|
||||
&.tabbed:focus + span:not(.lever):after {
|
||||
transform: scale(1);
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 10px rgba(0,0,0,.1);
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
}
|
||||
|
||||
[type="checkbox"]:checked {
|
||||
+ span:not(.lever):before {
|
||||
top: -4px;
|
||||
left: -5px;
|
||||
width: 12px;
|
||||
height: 22px;
|
||||
border-top: 2px solid transparent;
|
||||
border-left: 2px solid transparent;
|
||||
border-right: $radio-border;
|
||||
border-bottom: $radio-border;
|
||||
transform: rotate(40deg);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
&:disabled + span:before {
|
||||
border-right: 2px solid $input-disabled-color;
|
||||
border-bottom: 2px solid $input-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
/* Indeterminate checkbox */
|
||||
[type="checkbox"]:indeterminate {
|
||||
+ span:not(.lever):before {
|
||||
top: -11px;
|
||||
left: -12px;
|
||||
width: 10px;
|
||||
height: 22px;
|
||||
border-top: none;
|
||||
border-left: none;
|
||||
border-right: $radio-border;
|
||||
border-bottom: none;
|
||||
transform: rotate(90deg);
|
||||
backface-visibility: hidden;
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
// Disabled indeterminate
|
||||
&:disabled + span:not(.lever):before {
|
||||
border-right: 2px solid $input-disabled-color;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// Filled in Style
|
||||
[type="checkbox"].filled-in {
|
||||
// General
|
||||
+ span:not(.lever):after {
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
+ span:not(.lever):before,
|
||||
+ span:not(.lever):after {
|
||||
content: '';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
/* .1s delay is for check animation */
|
||||
transition: border .25s, background-color .25s, width .20s .1s, height .20s .1s, top .20s .1s, left .20s .1s;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
// Unchecked style
|
||||
&:not(:checked) + span:not(.lever):before {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 3px solid transparent;
|
||||
left: 6px;
|
||||
top: 10px;
|
||||
transform: rotateZ(37deg);
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
&:not(:checked) + span:not(.lever):after {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background-color: transparent;
|
||||
border: 2px solid $radio-empty-color;
|
||||
top: 0px;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
// Checked style
|
||||
&:checked {
|
||||
+ span:not(.lever):before {
|
||||
top: 0;
|
||||
left: 1px;
|
||||
width: 8px;
|
||||
height: 13px;
|
||||
border-top: 2px solid transparent;
|
||||
border-left: 2px solid transparent;
|
||||
border-right: 2px solid $input-background;
|
||||
border-bottom: 2px solid $input-background;
|
||||
transform: rotateZ(37deg);
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
|
||||
+ span:not(.lever):after {
|
||||
top: 0;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid $secondary-color;
|
||||
background-color: $secondary-color;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Focused styles
|
||||
&.tabbed:focus + span:not(.lever):after {
|
||||
border-radius: 2px;
|
||||
border-color: $radio-empty-color;
|
||||
background-color: rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
&.tabbed:checked:focus + span:not(.lever):after {
|
||||
border-radius: 2px;
|
||||
background-color: $secondary-color;
|
||||
border-color: $secondary-color;
|
||||
}
|
||||
|
||||
// Disabled style
|
||||
&:disabled:not(:checked) + span:not(.lever):before {
|
||||
background-color: transparent;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
&:disabled:not(:checked) + span:not(.lever):after {
|
||||
border-color: transparent;
|
||||
background-color: $input-disabled-solid-color;
|
||||
}
|
||||
|
||||
&:disabled:checked + span:not(.lever):before {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&:disabled:checked + span:not(.lever):after {
|
||||
background-color: $input-disabled-solid-color;
|
||||
border-color: $input-disabled-solid-color;
|
||||
}
|
||||
}
|
||||
44
assets/static/sass/components/forms/_file-input.scss
Normal file
44
assets/static/sass/components/forms/_file-input.scss
Normal file
@@ -0,0 +1,44 @@
|
||||
/* File Input
|
||||
========================================================================== */
|
||||
|
||||
.file-field {
|
||||
position: relative;
|
||||
|
||||
.file-path-wrapper {
|
||||
overflow: hidden;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
input.file-path { width: 100%; }
|
||||
|
||||
.btn {
|
||||
float: left;
|
||||
height: $input-height;
|
||||
line-height: $input-height;
|
||||
}
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=file] {
|
||||
|
||||
// Needed to override webkit button
|
||||
&::-webkit-file-upload-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0);
|
||||
}
|
||||
}
|
||||
22
assets/static/sass/components/forms/_forms.scss
Normal file
22
assets/static/sass/components/forms/_forms.scss
Normal file
@@ -0,0 +1,22 @@
|
||||
// Remove Focus Boxes
|
||||
select:focus {
|
||||
outline: $select-focus;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: none;
|
||||
background-color: $button-background-focus;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: $label-font-size;
|
||||
color: $input-border-color;
|
||||
}
|
||||
|
||||
@import 'input-fields';
|
||||
@import 'radio-buttons';
|
||||
@import 'checkboxes';
|
||||
@import 'switches';
|
||||
@import 'select';
|
||||
@import 'file-input';
|
||||
@import 'range';
|
||||
354
assets/static/sass/components/forms/_input-fields.scss
Normal file
354
assets/static/sass/components/forms/_input-fields.scss
Normal file
@@ -0,0 +1,354 @@
|
||||
/* Text Inputs + Textarea
|
||||
========================================================================== */
|
||||
|
||||
/* Style Placeholders */
|
||||
|
||||
::placeholder {
|
||||
color: $placeholder-text-color;
|
||||
}
|
||||
|
||||
/* Text inputs */
|
||||
|
||||
input:not([type]),
|
||||
input[type=text]:not(.browser-default),
|
||||
input[type=password]:not(.browser-default),
|
||||
input[type=email]:not(.browser-default),
|
||||
input[type=url]:not(.browser-default),
|
||||
input[type=time]:not(.browser-default),
|
||||
input[type=date]:not(.browser-default),
|
||||
input[type=datetime]:not(.browser-default),
|
||||
input[type=datetime-local]:not(.browser-default),
|
||||
input[type=tel]:not(.browser-default),
|
||||
input[type=number]:not(.browser-default),
|
||||
input[type=search]:not(.browser-default),
|
||||
textarea.materialize-textarea {
|
||||
|
||||
// General Styles
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-bottom: $input-border;
|
||||
border-radius: 0;
|
||||
outline: none;
|
||||
height: $input-height;
|
||||
width: 100%;
|
||||
font-size: $input-font-size;
|
||||
margin: $input-margin;
|
||||
padding: $input-padding;
|
||||
box-shadow: none;
|
||||
box-sizing: content-box;
|
||||
transition: box-shadow .3s, border .3s;
|
||||
|
||||
// Disabled input style
|
||||
&:disabled,
|
||||
&[readonly="readonly"] {
|
||||
color: $input-disabled-color;
|
||||
border-bottom: $input-disabled-border;
|
||||
}
|
||||
|
||||
// Disabled label style
|
||||
&:disabled+label,
|
||||
&[readonly="readonly"]+label {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
|
||||
// Focused input style
|
||||
&:focus:not([readonly]) {
|
||||
border-bottom: 1px solid $input-focus-color;
|
||||
box-shadow: 0 1px 0 0 $input-focus-color;
|
||||
}
|
||||
|
||||
// Focused label style
|
||||
&:focus:not([readonly])+label {
|
||||
color: $input-focus-color;
|
||||
}
|
||||
|
||||
// Hide helper text on data message
|
||||
&.valid ~ .helper-text[data-success],
|
||||
&:focus.valid ~ .helper-text[data-success],
|
||||
&.invalid ~ .helper-text[data-error],
|
||||
&:focus.invalid ~ .helper-text[data-error] {
|
||||
@extend %hidden-text;
|
||||
}
|
||||
|
||||
// Valid Input Style
|
||||
&.valid,
|
||||
&:focus.valid {
|
||||
@extend %valid-input-style;
|
||||
}
|
||||
|
||||
// Custom Success Message
|
||||
&.valid ~ .helper-text:after,
|
||||
&:focus.valid ~ .helper-text:after {
|
||||
@extend %custom-success-message;
|
||||
}
|
||||
&:focus.valid ~ label {
|
||||
color: $input-success-color;
|
||||
}
|
||||
|
||||
// Invalid Input Style
|
||||
&.invalid,
|
||||
&:focus.invalid {
|
||||
@extend %invalid-input-style;
|
||||
}
|
||||
|
||||
// Custom Error message
|
||||
&.invalid ~ .helper-text:after,
|
||||
&:focus.invalid ~ .helper-text:after {
|
||||
@extend %custom-error-message;
|
||||
}
|
||||
&:focus.invalid ~ label {
|
||||
color: $input-error-color;
|
||||
}
|
||||
|
||||
// Full width label when using validate for error messages
|
||||
&.validate + label {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// Form Message Shared Styles
|
||||
& + label:after {
|
||||
@extend %input-after-style;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Validation Sass Placeholders */
|
||||
%valid-input-style {
|
||||
border-bottom: 1px solid $input-success-color;
|
||||
box-shadow: 0 1px 0 0 $input-success-color;
|
||||
}
|
||||
%invalid-input-style {
|
||||
border-bottom: $input-invalid-border;
|
||||
box-shadow: 0 1px 0 0 $input-error-color;
|
||||
}
|
||||
%hidden-text {
|
||||
color: transparent;
|
||||
user-select: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
%custom-success-message {
|
||||
content: attr(data-success);
|
||||
color: $input-success-color;
|
||||
}
|
||||
%custom-error-message {
|
||||
content: attr(data-error);
|
||||
color: $input-error-color;
|
||||
}
|
||||
%input-after-style {
|
||||
display: block;
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
opacity: 0;
|
||||
transition: .2s opacity ease-out, .2s color ease-out;
|
||||
}
|
||||
|
||||
|
||||
// Styling for input field wrapper
|
||||
.input-field {
|
||||
// Inline styles
|
||||
&.inline {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 5px;
|
||||
|
||||
input,
|
||||
.select-dropdown {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Gutter spacing
|
||||
&.col {
|
||||
label {
|
||||
left: $gutter-width / 2;
|
||||
}
|
||||
|
||||
.prefix ~ label,
|
||||
.prefix ~ .validate ~ label {
|
||||
width: calc(100% - 3rem - #{$gutter-width});
|
||||
}
|
||||
}
|
||||
|
||||
position: relative;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
& > label {
|
||||
color: $input-border-color;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: 1rem;
|
||||
cursor: text;
|
||||
transition: transform .2s ease-out, color .2s ease-out;
|
||||
transform-origin: 0% 100%;
|
||||
text-align: initial;
|
||||
transform: translateY(12px);
|
||||
|
||||
&:not(.label-icon).active {
|
||||
transform: translateY(-14px) scale(.8);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Autofill + date + time inputs
|
||||
& > input[type]:-webkit-autofill:not(.browser-default) + label,
|
||||
& > input[type=date]:not(.browser-default) + label,
|
||||
& > input[type=time]:not(.browser-default) + label {
|
||||
transform: translateY(-14px) scale(.8);
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
.helper-text {
|
||||
&::after {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
min-height: 18px;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
color: rgba(0,0,0,.54);
|
||||
}
|
||||
|
||||
// Prefix Icons
|
||||
.prefix {
|
||||
position: absolute;
|
||||
width: $input-height;
|
||||
font-size: $input-icon-size;
|
||||
transition: color .2s;
|
||||
top: ($input-height - $input-icon-size) / 2;
|
||||
|
||||
&.active { color: $input-focus-color; }
|
||||
}
|
||||
|
||||
.prefix ~ input,
|
||||
.prefix ~ textarea,
|
||||
.prefix ~ label,
|
||||
.prefix ~ .validate ~ label,
|
||||
.prefix ~ .helper-text,
|
||||
.prefix ~ .autocomplete-content {
|
||||
margin-left: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.prefix ~ label { margin-left: 3rem; }
|
||||
|
||||
@media #{$medium-and-down} {
|
||||
.prefix ~ input {
|
||||
width: 86%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
}
|
||||
|
||||
@media #{$small-and-down} {
|
||||
.prefix ~ input {
|
||||
width: 80%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Search Field */
|
||||
|
||||
.input-field input[type=search] {
|
||||
display: block;
|
||||
line-height: inherit;
|
||||
transition: .3s background-color;
|
||||
|
||||
.nav-wrapper & {
|
||||
height: inherit;
|
||||
padding-left: 4rem;
|
||||
width: calc(100% - 4rem);
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&:focus:not(.browser-default) {
|
||||
background-color: $input-background;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
color: #444;
|
||||
|
||||
& + label i,
|
||||
& ~ .mdi-navigation-close,
|
||||
& ~ .material-icons {
|
||||
color: #444;
|
||||
}
|
||||
}
|
||||
|
||||
& + .label-icon {
|
||||
transform: none;
|
||||
left: 1rem;
|
||||
}
|
||||
|
||||
& ~ .mdi-navigation-close,
|
||||
& ~ .material-icons {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 1rem;
|
||||
color: transparent;
|
||||
cursor: pointer;
|
||||
font-size: $input-icon-size;
|
||||
transition: .3s color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Textarea */
|
||||
|
||||
// Default textarea
|
||||
textarea {
|
||||
width: 100%;
|
||||
height: $input-height;
|
||||
background-color: transparent;
|
||||
|
||||
&.materialize-textarea {
|
||||
line-height: normal;
|
||||
overflow-y: hidden; /* prevents scroll bar flash */
|
||||
padding: .8rem 0 .8rem 0; /* prevents text jump on Enter keypress */
|
||||
resize: none;
|
||||
min-height: $input-height;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
// For textarea autoresize
|
||||
.hiddendiv {
|
||||
visibility: hidden;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word; /* future version of deprecated 'word-wrap' */
|
||||
padding-top: 1.2rem; /* prevents text jump on Enter keypress */
|
||||
|
||||
// Reduces repaints
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
/* Autocomplete */
|
||||
.autocomplete-content {
|
||||
li {
|
||||
.highlight { color: #444; }
|
||||
|
||||
img {
|
||||
height: $dropdown-item-height - 10;
|
||||
width: $dropdown-item-height - 10;
|
||||
margin: 5px 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Character Counter */
|
||||
.character-counter {
|
||||
min-height: 18px;
|
||||
}
|
||||
115
assets/static/sass/components/forms/_radio-buttons.scss
Normal file
115
assets/static/sass/components/forms/_radio-buttons.scss
Normal file
@@ -0,0 +1,115 @@
|
||||
/* Radio Buttons
|
||||
========================================================================== */
|
||||
|
||||
// Remove default Radio Buttons
|
||||
[type="radio"]:not(:checked),
|
||||
[type="radio"]:checked {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + span,
|
||||
[type="radio"]:checked + span {
|
||||
position: relative;
|
||||
padding-left: 35px;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 1rem;
|
||||
transition: .28s ease;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[type="radio"] + span:before,
|
||||
[type="radio"] + span:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 4px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
z-index: 0;
|
||||
transition: .28s ease;
|
||||
}
|
||||
|
||||
/* Unchecked styles */
|
||||
[type="radio"]:not(:checked) + span:before,
|
||||
[type="radio"]:not(:checked) + span:after,
|
||||
[type="radio"]:checked + span:before,
|
||||
[type="radio"]:checked + span:after,
|
||||
[type="radio"].with-gap:checked + span:before,
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + span:before,
|
||||
[type="radio"]:not(:checked) + span:after {
|
||||
border: 2px solid $radio-empty-color;
|
||||
}
|
||||
|
||||
[type="radio"]:not(:checked) + span:after {
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
/* Checked styles */
|
||||
[type="radio"]:checked + span:before {
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
[type="radio"]:checked + span:after,
|
||||
[type="radio"].with-gap:checked + span:before,
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
border: $radio-border;
|
||||
}
|
||||
|
||||
[type="radio"]:checked + span:after,
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
background-color: $radio-fill-color;
|
||||
}
|
||||
|
||||
[type="radio"]:checked + span:after {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
/* Radio With gap */
|
||||
[type="radio"].with-gap:checked + span:after {
|
||||
transform: scale(.5);
|
||||
}
|
||||
|
||||
/* Focused styles */
|
||||
[type="radio"].tabbed:focus + span:before {
|
||||
box-shadow: 0 0 0 10px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
/* Disabled Radio With gap */
|
||||
[type="radio"].with-gap:disabled:checked + span:before {
|
||||
border: 2px solid $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"].with-gap:disabled:checked + span:after {
|
||||
border: none;
|
||||
background-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
/* Disabled style */
|
||||
[type="radio"]:disabled:not(:checked) + span:before,
|
||||
[type="radio"]:disabled:checked + span:before {
|
||||
background-color: transparent;
|
||||
border-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"]:disabled + span {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"]:disabled:not(:checked) + span:before {
|
||||
border-color: $input-disabled-color;
|
||||
}
|
||||
|
||||
[type="radio"]:disabled:checked + span:after {
|
||||
background-color: $input-disabled-color;
|
||||
border-color: $input-disabled-solid-color;
|
||||
}
|
||||
161
assets/static/sass/components/forms/_range.scss
Normal file
161
assets/static/sass/components/forms/_range.scss
Normal file
@@ -0,0 +1,161 @@
|
||||
/* Range
|
||||
========================================================================== */
|
||||
|
||||
.range-field {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
input[type=range],
|
||||
input[type=range] + .thumb {
|
||||
@extend .no-select;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type=range] {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
margin: 15px 0;
|
||||
padding: 0;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=range] + .thumb {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 0;
|
||||
border: none;
|
||||
height: 0;
|
||||
width: 0;
|
||||
border-radius: 50%;
|
||||
background-color: $radio-fill-color;
|
||||
margin-left: 7px;
|
||||
|
||||
transform-origin: 50% 50%;
|
||||
transform: rotate(-45deg);
|
||||
|
||||
.value {
|
||||
display: block;
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
color: $radio-fill-color;
|
||||
font-size: 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&.active {
|
||||
border-radius: 50% 50% 50% 0;
|
||||
|
||||
.value {
|
||||
color: $input-background;
|
||||
margin-left: -1px;
|
||||
margin-top: 8px;
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shared
|
||||
@mixin range-track {
|
||||
height: $track-height;
|
||||
background: #c2c0c2;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@mixin range-thumb {
|
||||
border: none;
|
||||
height: $range-height;
|
||||
width: $range-width;
|
||||
border-radius: 50%;
|
||||
background: $radio-fill-color;
|
||||
transition: box-shadow .3s;
|
||||
}
|
||||
|
||||
// WebKit
|
||||
input[type=range] {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-runnable-track {
|
||||
@include range-track;
|
||||
}
|
||||
|
||||
input[type=range]::-webkit-slider-thumb {
|
||||
@include range-thumb;
|
||||
-webkit-appearance: none;
|
||||
background-color: $radio-fill-color;
|
||||
transform-origin: 50% 50%;
|
||||
margin: -5px 0 0 0;
|
||||
|
||||
}
|
||||
|
||||
.keyboard-focused input[type=range]:focus:not(.active)::-webkit-slider-thumb {
|
||||
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
|
||||
}
|
||||
|
||||
// FireFox
|
||||
input[type=range] {
|
||||
/* fix for FF unable to apply focus style bug */
|
||||
border: 1px solid white;
|
||||
|
||||
/*required for proper track sizing in FF*/
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-track {
|
||||
@include range-track;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
input[type=range]::-moz-range-thumb {
|
||||
@include range-thumb;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
// hide the outline behind the border
|
||||
input[type=range]:-moz-focusring {
|
||||
outline: 1px solid #fff;
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.keyboard-focused input[type=range]:focus:not(.active)::-moz-range-thumb {
|
||||
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
|
||||
}
|
||||
|
||||
// IE 10+
|
||||
input[type=range]::-ms-track {
|
||||
height: $track-height;
|
||||
|
||||
// remove bg colour from the track, we'll use ms-fill-lower and ms-fill-upper instead
|
||||
background: transparent;
|
||||
|
||||
// leave room for the larger thumb to overflow with a transparent border */
|
||||
border-color: transparent;
|
||||
border-width: 6px 0;
|
||||
|
||||
/*remove default tick marks*/
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-fill-lower {
|
||||
background: #777;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-fill-upper {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
input[type=range]::-ms-thumb {
|
||||
@include range-thumb;
|
||||
}
|
||||
|
||||
.keyboard-focused input[type=range]:focus:not(.active)::-ms-thumb {
|
||||
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
|
||||
}
|
||||
180
assets/static/sass/components/forms/_select.scss
Normal file
180
assets/static/sass/components/forms/_select.scss
Normal file
@@ -0,0 +1,180 @@
|
||||
/* Select Field
|
||||
========================================================================== */
|
||||
|
||||
select { display: none; }
|
||||
select.browser-default { display: block; }
|
||||
|
||||
select {
|
||||
background-color: $select-background;
|
||||
width: 100%;
|
||||
padding: $select-padding;
|
||||
border: $select-border;
|
||||
border-radius: $select-radius;
|
||||
height: $input-height;
|
||||
}
|
||||
|
||||
.select-label {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.select-wrapper {
|
||||
&.valid .helper-text[data-success],
|
||||
&.invalid ~ .helper-text[data-error] {
|
||||
@extend %hidden-text;
|
||||
}
|
||||
|
||||
&.valid {
|
||||
& > input.select-dropdown {
|
||||
@extend %valid-input-style;
|
||||
}
|
||||
|
||||
& ~ .helper-text:after {
|
||||
@extend %custom-success-message;
|
||||
}
|
||||
}
|
||||
|
||||
&.invalid {
|
||||
& > input.select-dropdown,
|
||||
& > input.select-dropdown:focus {
|
||||
@extend %invalid-input-style;
|
||||
}
|
||||
|
||||
& ~ .helper-text:after {
|
||||
@extend %custom-error-message;
|
||||
}
|
||||
}
|
||||
|
||||
&.valid + label,
|
||||
&.invalid + label {
|
||||
width: 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
& + label:after {
|
||||
@extend %input-after-style;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
|
||||
input.select-dropdown {
|
||||
&:focus {
|
||||
border-bottom: 1px solid $input-focus-color;
|
||||
}
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
border-bottom: $input-border;
|
||||
outline: none;
|
||||
height: $input-height;
|
||||
line-height: $input-height;
|
||||
width: 100%;
|
||||
font-size: $input-font-size;
|
||||
margin: $input-margin;
|
||||
padding: 0;
|
||||
display: block;
|
||||
user-select:none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.caret {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
z-index: 0;
|
||||
fill: rgba(0,0,0,.87);
|
||||
}
|
||||
|
||||
& + label {
|
||||
position: absolute;
|
||||
top: -26px;
|
||||
font-size: $label-font-size;
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled styles
|
||||
select:disabled {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
|
||||
.select-wrapper.disabled {
|
||||
+ label {
|
||||
color: $input-disabled-color;
|
||||
}
|
||||
.caret {
|
||||
fill: $input-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
.select-wrapper input.select-dropdown:disabled {
|
||||
color: $input-disabled-color;
|
||||
cursor: default;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.select-wrapper i {
|
||||
color: $select-disabled-color;
|
||||
}
|
||||
|
||||
.select-dropdown li.disabled,
|
||||
.select-dropdown li.disabled > span,
|
||||
.select-dropdown li.optgroup {
|
||||
color: $select-disabled-color;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
body.keyboard-focused {
|
||||
.select-dropdown.dropdown-content li:focus {
|
||||
background-color: $select-option-focus;
|
||||
}
|
||||
}
|
||||
|
||||
.select-dropdown.dropdown-content {
|
||||
li {
|
||||
&:hover {
|
||||
background-color: $select-option-hover;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: $select-option-selected;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix Icons
|
||||
.prefix ~ .select-wrapper {
|
||||
margin-left: 3rem;
|
||||
width: 92%;
|
||||
width: calc(100% - 3rem);
|
||||
}
|
||||
|
||||
.prefix ~ label { margin-left: 3rem; }
|
||||
|
||||
// Icons
|
||||
.select-dropdown li {
|
||||
img {
|
||||
height: $dropdown-item-height - 10;
|
||||
width: $dropdown-item-height - 10;
|
||||
margin: 5px 15px;
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
// Optgroup styles
|
||||
.select-dropdown li.optgroup {
|
||||
border-top: 1px solid $dropdown-hover-bg-color;
|
||||
|
||||
&.selected > span {
|
||||
color: rgba(0, 0, 0, .7);
|
||||
}
|
||||
|
||||
& > span {
|
||||
color: rgba(0, 0, 0, .4);
|
||||
}
|
||||
|
||||
& ~ li.optgroup-option {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
}
|
||||
89
assets/static/sass/components/forms/_switches.scss
Normal file
89
assets/static/sass/components/forms/_switches.scss
Normal file
@@ -0,0 +1,89 @@
|
||||
/* Switch
|
||||
========================================================================== */
|
||||
|
||||
.switch,
|
||||
.switch * {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.switch label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.switch label input[type=checkbox] {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
||||
&:checked + .lever {
|
||||
background-color: $switch-checked-lever-bg;
|
||||
|
||||
&:before, &:after {
|
||||
left: 18px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
background-color: $switch-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.switch label .lever {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: 36px;
|
||||
height: 14px;
|
||||
background-color: $switch-unchecked-lever-bg;
|
||||
border-radius: $switch-radius;
|
||||
margin-right: 10px;
|
||||
transition: background 0.3s ease;
|
||||
vertical-align: middle;
|
||||
margin: 0 16px;
|
||||
|
||||
&:before, &:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
left: 0;
|
||||
top: -3px;
|
||||
transition: left 0.3s ease, background .3s ease, box-shadow 0.1s ease, transform .1s ease;
|
||||
}
|
||||
|
||||
&:before {
|
||||
background-color: transparentize($switch-bg-color, .85);
|
||||
}
|
||||
|
||||
&:after {
|
||||
background-color: $switch-unchecked-bg;
|
||||
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch active style
|
||||
input[type=checkbox]:checked:not(:disabled) ~ .lever:active::before,
|
||||
input[type=checkbox]:checked:not(:disabled).tabbed:focus ~ .lever::before {
|
||||
transform: scale(2.4);
|
||||
background-color: transparentize($switch-bg-color, .85);
|
||||
}
|
||||
|
||||
input[type=checkbox]:not(:disabled) ~ .lever:active:before,
|
||||
input[type=checkbox]:not(:disabled).tabbed:focus ~ .lever::before {
|
||||
transform: scale(2.4);
|
||||
background-color: rgba(0,0,0,.08);
|
||||
}
|
||||
|
||||
// Disabled Styles
|
||||
.switch input[type=checkbox][disabled] + .lever {
|
||||
cursor: default;
|
||||
background-color: rgba(0,0,0,.12);
|
||||
}
|
||||
|
||||
.switch label input[type=checkbox][disabled] + .lever:after,
|
||||
.switch label input[type=checkbox][disabled]:checked + .lever:after {
|
||||
background-color: $input-disabled-solid-color;
|
||||
}
|
||||
138
assets/static/sass/materialize.scss
vendored
Normal file
138
assets/static/sass/materialize.scss
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
// Color
|
||||
@import "components/color-variables";
|
||||
@import "components/color-classes";
|
||||
|
||||
// Variables;
|
||||
@import "components/variables";
|
||||
|
||||
// Reset
|
||||
@import "components/normalize";
|
||||
|
||||
// components
|
||||
@import "components/mixins";
|
||||
@import "components/global";
|
||||
@import "components/badges";
|
||||
@import "components/icons-material-design";
|
||||
@import "components/grid";
|
||||
@import "components/navbar";
|
||||
@import "components/typography";
|
||||
@import "components/transitions";
|
||||
@import "components/cards";
|
||||
@import "components/toast";
|
||||
@import "components/tabs";
|
||||
@import "components/tooltip";
|
||||
@import "components/buttons";
|
||||
@import "components/dropdown";
|
||||
@import "components/waves";
|
||||
@import "components/modal";
|
||||
@import "components/collapsible";
|
||||
@import "components/chips";
|
||||
@import "components/materialbox";
|
||||
@import "components/forms/forms";
|
||||
@import "components/table_of_contents";
|
||||
@import "components/sidenav";
|
||||
@import "components/preloader";
|
||||
@import "components/slider";
|
||||
@import "components/carousel";
|
||||
@import "components/tapTarget";
|
||||
@import "components/pulse";
|
||||
@import "components/datepicker";
|
||||
@import "components/timepicker";
|
||||
|
||||
#full-div {
|
||||
//width: 100vw;
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
width: 80% !important;
|
||||
}
|
||||
|
||||
.nav-wrapper {
|
||||
padding: 0 10%;
|
||||
}
|
||||
|
||||
nav {
|
||||
>div>ul>li>a {
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
.panel {
|
||||
background-color: color('grey', 'lighten-5');
|
||||
border: 1px solid $primary-color;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
color: white;
|
||||
background-color: $primary-color;
|
||||
border-color: #bce8f1;
|
||||
|
||||
padding: 10px 15px;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-top-right-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
padding: 15px;
|
||||
|
||||
&.quick-actions {
|
||||
>:last-child{
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
>:first-child {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
$dl-horizontal-breakpoint: 768px;
|
||||
$dl-horizontal-offset: 160px !default;
|
||||
|
||||
.dl-horizontal {
|
||||
dd {
|
||||
@include clearfix; // Clear the floated `dt` if an empty `dd` is present
|
||||
}
|
||||
|
||||
@media (min-width: $dl-horizontal-breakpoint) {
|
||||
dt {
|
||||
float: left;
|
||||
width: ($dl-horizontal-offset - 20);
|
||||
clear: left;
|
||||
text-align: right;
|
||||
@include text-overflow;
|
||||
}
|
||||
dd {
|
||||
margin-left: $dl-horizontal-offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-group {
|
||||
>button {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.no-pad {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.bold-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.disabled_input {
|
||||
color: rgba(0, 0, 0, 0.42);
|
||||
border-bottom: 1px dotted rgba(0, 0, 0, 0.42) !important;
|
||||
cursor: default;
|
||||
}
|
||||
47
assets/templates/asset_list.html
Normal file
47
assets/templates/asset_list.html
Normal file
@@ -0,0 +1,47 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}List{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h4>Asset List</h4>
|
||||
|
||||
<form method="post" id="asset-filter-form" class="row">
|
||||
{% csrf_token %}
|
||||
<div class="input-field col l11 s12">
|
||||
<input type="text" name="asset_id">
|
||||
<label for="asset_id">Asset ID</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col l1 offset-s4">
|
||||
<button type="submit" class="btn">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Asset ID</th>
|
||||
<th>Description</th>
|
||||
<th>Category</th>
|
||||
<th>Status</th>
|
||||
<th>Quick Links</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="asset_table_body">
|
||||
{% include 'asset_list_table_body.html' %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% include 'helpers/paginator.html' %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
$('#asset-filter-form').on('submit', function (event) {
|
||||
event.preventDefault();
|
||||
filterAssetTable();
|
||||
return false;
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
14
assets/templates/asset_list_table_body.html
Normal file
14
assets/templates/asset_list_table_body.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% for item in object_list %}
|
||||
{# <li><a href="{% url 'asset_detail' item.pk %}">{{ item.asset_id }} - {{ item.description }}</a></li>#}
|
||||
<tr>
|
||||
<td><a href="{% url 'asset_detail' item.pk %}">{{ item.asset_id }}</a></td>
|
||||
<td>{{ item.description }}</td>
|
||||
<td>{{ item.category }}</td>
|
||||
<td>{{ item.status }}</td>
|
||||
<td>
|
||||
<a href="{% url 'asset_detail' item.pk %}"><i class="material-icons">visibility</i></a>
|
||||
<a href="{% url 'asset_update' item.pk %}"><i class="material-icons">edit</i></a>
|
||||
<a href="{% url 'asset_update' item.pk %}?duplicate=true"><i class="material-icons">content_copy</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
327
assets/templates/asset_update.html
Normal file
327
assets/templates/asset_update.html
Normal file
@@ -0,0 +1,327 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load widget_tweaks %}
|
||||
{% load asset_templatetags %}
|
||||
{% block title %}Asset {{ object.asset_id }}{% endblock %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h4>
|
||||
{% if edit and object %}
|
||||
Edit Asset | {{ object.asset_id }}
|
||||
{% elif duplicate %}
|
||||
Duplication of Asset | {{ previous_asset_id }}
|
||||
{% elif not object %}
|
||||
Create Asset
|
||||
{% else %}
|
||||
Asset | {{ object.asset_id }}
|
||||
{% endif %}
|
||||
|
||||
</h4>
|
||||
<div class="divider"></div>
|
||||
|
||||
<br>
|
||||
|
||||
<form method="post" id="asset_update_form">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="id" value="{{ object.id|default:0 }}">
|
||||
|
||||
<div class="row">
|
||||
<div class="col s12">
|
||||
<div class="button-group right">
|
||||
{% if edit and object %}
|
||||
<!--edit-->
|
||||
<button type="button" class="btn" onclick="updateAsset()">Save</button>
|
||||
<a class="waves-effect waves-light btn" href="{% url 'asset_update' object.pk %}?duplicate=true">Duplicate</a>
|
||||
<a class="waves-effect waves-light btn modal-trigger" href="#confirm_delete_modal">Delete</a>
|
||||
{% elif duplicate %}
|
||||
<!--duplicate-->
|
||||
<button type="button" class="btn" onclick="updateAsset()">Create Duplicate</button>
|
||||
<a href="{% url 'asset_detail' previous_asset_pk %}" class="btn">Cancel</a>
|
||||
{% elif not object %}
|
||||
<!--create-->
|
||||
<button type="button" class="btn" onclick="updateAsset()">Save</button>
|
||||
{% else %}
|
||||
<!--detail-->
|
||||
<a href="{% url 'asset_update' object.pk %}" class="btn">Edit</a>
|
||||
<a class="waves-effect waves-light btn" href="{% url 'asset_update' object.pk %}?duplicate=true">Duplicate</a>
|
||||
<a class="waves-effect waves-light btn modal-trigger" href="#confirm_delete_modal">Delete</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
Asset Details
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
{% if edit or duplicate %}
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
{% if duplicate %}
|
||||
{% render_field form.asset_id value=object.asset_id %}
|
||||
{% elif object.asset_id %}
|
||||
{% render_field form.asset_id|attr:'readonly'|add_class:'disabled_input' value=object.asset_id %}
|
||||
{% else %}
|
||||
{% render_field form.asset_id %}
|
||||
{% endif %}
|
||||
<label for="{{ form.asset_id.id_for_label }}" class="bold-text">Asset ID</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% render_field form.description value=object.description %}
|
||||
<label for="{{ form.description.id_for_label }}"
|
||||
class="bold-text">Description</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
<select name="{{ form.category.name }}" id="{{ form.category.id_for_label }}"
|
||||
required>
|
||||
{% for id, choice in form.category.field.choices %}
|
||||
<option value="{{ id }}"
|
||||
{% if object.category.id == id %}selected{% endif %}>{{ choice }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label for="{{ form.category.id_for_label }}" class="bold-text">Category</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
<select name="{{ form.status.name }}" id="{{ form.status.id_for_label }}" required>
|
||||
{% for id, choice in form.status.field.choices %}
|
||||
<option value="{{ id }}"
|
||||
{% if not object.status.id and choice == "Active" or object.status.id == id %}selected{% endif %}>{{ choice }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label for="{{ form.status.id_for_label }}" class="bold-text">Status</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% render_field form.serial_number value=object.serial_number %}
|
||||
<label for="{{ form.serial_number.id_for_label }}">Serial Number</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% render_field form.comments|add_class:'materialize-textarea' %}
|
||||
<label for="{{ form.comments.id_for_label }}">Comments</label>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<dt>Asset ID</dt>
|
||||
<dd>{{ object.asset_id }}</dd>
|
||||
|
||||
<dt>Description</dt>
|
||||
<dd>{{ object.description }}</dd>
|
||||
|
||||
<dt>Category</dt>
|
||||
<dd>{{ object.category }}</dd>
|
||||
|
||||
<dt>Status</dt>
|
||||
<dd>{{ object.status }}</dd>
|
||||
|
||||
<dt>Serial Number</dt>
|
||||
<dd>{{ object.serial_number|default:'-' }}</dd>
|
||||
|
||||
<dt>Comments</dt>
|
||||
<dd>{{ object.comments|default:'-'|linebreaksbr }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
Purchase Details
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
{% if edit or duplicate %}
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<select name="{{ form.purchased_from.name }}"
|
||||
id="{{ form.purchased_from.id_for_label }}">
|
||||
{% for id, choice in form.purchased_from.field.choices %}
|
||||
<option value="{{ id }}"
|
||||
{% if object.purchased_from.id == id %}selected{% endif %}>{{ choice }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label for="{{ form.purchased_from.id_for_label }}">Purchased From</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% render_field form.purchase_price value=object.purchase_price %}
|
||||
<label for="{{ form.purchase_price.id_for_label }}">Purchase Price</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% render_field form.salvage_value value=object.salvage_value %}
|
||||
<label for="{{ form.salvage_value.id_for_label }}">Salvage Value</label>
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% if object.date_acquired %}
|
||||
{% render_field form.date_acquired|add_class:'datepicker' value=object.date_acquired|date %}
|
||||
{% else %}
|
||||
<input type="text" name="date_acquired" value="{% now "DATE_FORMAT" %}"
|
||||
class="datepicker" id="id_date_acquired">
|
||||
{% endif %}
|
||||
<label for="{{ form.date_acquired.id_for_label }}" class="bold-text">Date
|
||||
Acquired</label>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="input-field col s12">
|
||||
{% render_field form.date_sold|add_class:'datepicker' value=object.date_sold|date %}
|
||||
<label for="{{ form.date_sold.id_for_label }}">Date Sold</label>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<dt>Purchased From</dt>
|
||||
<dd>{{ object.purchased_from|default_if_none:'-' }}</dd>
|
||||
|
||||
<dt>Purchase Price</dt>
|
||||
<dd>£{{ object.purchase_price|default_if_none:'-' }}</dd>
|
||||
|
||||
<dt>Salvage Value</dt>
|
||||
<dd>£{{ object.salvage_value|default_if_none:'-' }}</dd>
|
||||
|
||||
<dt>Date Acquired</dt>
|
||||
<dd>{{ object.date_acquired|default_if_none:'-' }}</dd>
|
||||
|
||||
<dt>Date Sold</dt>
|
||||
<dd>{{ object.date_sold|default_if_none:'-' }}</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if object.is_cable %}
|
||||
<div class="row">
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
Cable Details
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
<dt>Length</dt>
|
||||
<dd>{{ object.length }}m</dd>
|
||||
|
||||
<dt>Type</dt>
|
||||
<dd>TODO</dd>
|
||||
|
||||
<dt>Required CSA</dt>
|
||||
<dd>TODO</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="panel">
|
||||
<div class="panel-heading">
|
||||
Collection Details
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<dl class="dl-horizontal">
|
||||
{% if edit or duplicate %}
|
||||
<div class="row">
|
||||
|
||||
<div class="input-field col s10">
|
||||
<input type="hidden" name="{{ form.parent.html_name }}" id="hidden_parent_id"
|
||||
value="{{ object.parent.id }}">
|
||||
<input type="text" id="parent_id" value="{{ object.parent|default:'' }}"
|
||||
disabled="">
|
||||
<label for="parent_id">Parent</label>
|
||||
</div>
|
||||
<div class="col s2">
|
||||
<button type="button" class="btn btn-flat" onclick="clearParent()">
|
||||
<i class="material-icons">clear</i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="input-field col s10">
|
||||
<input type="text" id="parent_search">
|
||||
<label for="parent_search">Search for asset</label>
|
||||
{# {% render_field form.parent value=object.parent %}#}
|
||||
</div>
|
||||
<div class="col s2">
|
||||
<button type="button" class="btn btn-flat" onclick="formAssetSearch()">
|
||||
<i class="material-icons">search</i>
|
||||
</button>
|
||||
<br>
|
||||
</div>
|
||||
<div class="col s12" id="formAssetSearchResult">
|
||||
<!--Placeholder for search results-->
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<dt>Parent</dt>
|
||||
<dd>
|
||||
{% if object.parent %}
|
||||
<a href="{% url 'asset_detail' object.parent.pk %}">
|
||||
{{ object.parent.asset_id }} - {{ object.parent.description }}
|
||||
</a>
|
||||
{% else %}
|
||||
<span>-</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
|
||||
<dt>Children</dt>
|
||||
{% if object.asset_parent.all %}
|
||||
{% for child in object.asset_parent.all %}
|
||||
<dd>
|
||||
<a href="{% url 'asset_detail' child.pk %}">
|
||||
{{ child.asset_id }} - {{ child.description }}
|
||||
</a>
|
||||
</dd>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<dd><span>-</span></dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% include 'confirm_delete.html' with object=object %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block script %}
|
||||
|
||||
{# <script>#}
|
||||
{# $('#asset_update_form').on('submit', function(event){#}
|
||||
{#console.log($('#asset_update_form').serialize());#}
|
||||
{# event.preventDefault();#}
|
||||
{# updateAsset();#}
|
||||
{# return false;#}
|
||||
{# });#}
|
||||
{# </script>#}
|
||||
|
||||
<script>
|
||||
function clearParent() {
|
||||
$('#hidden_parent_id').val('');
|
||||
$('#parent_id').val('');
|
||||
M.updateTextFields()
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
{% if edit or duplicate %}
|
||||
var comments_id = '#{{ form.comments.id_for_label }}';
|
||||
$(comments_id).val('{{ object.comments|linebreaksn }}');
|
||||
M.textareaAutoResize($(comments_id));
|
||||
{% endif %}
|
||||
M.updateTextFields();
|
||||
})
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
16
assets/templates/asset_update_search_results.html
Normal file
16
assets/templates/asset_update_search_results.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% for asset in object_list %}
|
||||
<a href="javascript:void(0);" onclick="insertInParentField({{ asset.pk }}, '{{ asset }}')">
|
||||
{{ asset.asset_id }} - {{ asset.description }}
|
||||
</a>
|
||||
<br>
|
||||
{% empty %}
|
||||
No assets match given ID
|
||||
{% endfor %}
|
||||
|
||||
<script>
|
||||
function insertInParentField(pk, str) {
|
||||
$('#hidden_parent_id').val(pk);
|
||||
$('#parent_id').val(str);
|
||||
M.updateTextFields();
|
||||
}
|
||||
</script>
|
||||
6
assets/templates/supplier_detail.html
Normal file
6
assets/templates/supplier_detail.html
Normal file
@@ -0,0 +1,6 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Detail{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{{ object }}
|
||||
{% endblock %}
|
||||
29
assets/templates/supplier_list.html
Normal file
29
assets/templates/supplier_list.html
Normal file
@@ -0,0 +1,29 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}List{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h4>Supplier List</h4>
|
||||
|
||||
<table class="striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Supplier</th>
|
||||
<th>Quick Links</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="asset_table_body">
|
||||
{% for item in object_list %}
|
||||
<tr>
|
||||
<td>{{ item.name }}</td>
|
||||
<td>
|
||||
<a href="{% url 'supplier_update' item.pk %}"><i class="material-icons">edit</i></a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{% include 'helpers/paginator.html' %}
|
||||
|
||||
{% endblock %}
|
||||
24
assets/templates/supplier_update.html
Normal file
24
assets/templates/supplier_update.html
Normal file
@@ -0,0 +1,24 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Edit{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<h4>
|
||||
Supplier
|
||||
{% if object %}
|
||||
Edit | {{ object.name }}
|
||||
{% else %}
|
||||
Create
|
||||
{% endif %}
|
||||
</h4>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
{{ form }}
|
||||
|
||||
<input type="submit" value="Save" class="btn">
|
||||
</form>
|
||||
{% endblock %}
|
||||
0
assets/templatetags/__init__.py
Normal file
0
assets/templatetags/__init__.py
Normal file
21
assets/templatetags/asset_templatetags.py
Normal file
21
assets/templatetags/asset_templatetags.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from django import template
|
||||
from django.template.defaultfilters import stringfilter
|
||||
from django.utils.safestring import SafeData, mark_safe
|
||||
from django.utils.text import normalize_newlines
|
||||
from django.utils.html import escape
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter(is_safe=True, needs_autoescape=True)
|
||||
@stringfilter
|
||||
def linebreaksn(value, autoescape=True):
|
||||
"""
|
||||
Convert all newlines in a piece of plain text to jQuery line breaks
|
||||
(`\n`).
|
||||
"""
|
||||
autoescape = autoescape and not isinstance(value, SafeData)
|
||||
value = normalize_newlines(value)
|
||||
if autoescape:
|
||||
value = escape(value)
|
||||
return mark_safe(value.replace('\n', '\\n'))
|
||||
3
assets/tests.py
Normal file
3
assets/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
26
assets/urls.py
Normal file
26
assets/urls.py
Normal file
@@ -0,0 +1,26 @@
|
||||
from django.urls import path, include
|
||||
from rest_framework import routers
|
||||
from assets import views, api
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'api/assets', api.AssetViewSet)
|
||||
|
||||
urlpatterns = [
|
||||
# path('', views.Index.as_view(), name='index'),
|
||||
path('', views.AssetList.as_view(), name='index'),
|
||||
path('asset/list/', views.AssetList.as_view(), name='asset_list'),
|
||||
path('asset/<int:pk>/', views.AssetDetail.as_view(), name='asset_detail'),
|
||||
path('asset/create/', views.AssetEdit.as_view(), name='asset_create'),
|
||||
path('asset/<int:pk>/edit/', views.AssetEdit.as_view(), name='asset_update'),
|
||||
path('asset/delete/', views.asset_delete, name='ajax_asset_delete'),
|
||||
path('asset/filter/', views.asset_filter, name='ajax_asset_filter'),
|
||||
path('asset/update/', views.asset_update, name='ajax_asset_update'),
|
||||
|
||||
path('supplier/list', views.SupplierList.as_view(), name='supplier_list'),
|
||||
path('supplier/<int:pk>', views.SupplierDetail.as_view(), name='supplier_detail'),
|
||||
path('supplier/create', views.SupplierCreate.as_view(), name='supplier_create'),
|
||||
path('supplier/<int:pk>/edit', views.SupplierUpdate.as_view(), name='supplier_update'),
|
||||
|
||||
path('', include(router.urls)),
|
||||
]
|
||||
|
||||
166
assets/views.py
Normal file
166
assets/views.py
Normal file
@@ -0,0 +1,166 @@
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpResponse, QueryDict
|
||||
from django.core import serializers
|
||||
from django.views import generic
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import reverse_lazy, reverse
|
||||
from django.db.models import Q
|
||||
import datetime
|
||||
from dateutil import parser
|
||||
# import json
|
||||
import simplejson as json
|
||||
from assets import models, forms
|
||||
|
||||
|
||||
class Login(auth_views.LoginView):
|
||||
template_name = 'registration/login.html'
|
||||
|
||||
|
||||
class Logout(auth_views.LogoutView):
|
||||
template_name = 'registration/logout.html'
|
||||
|
||||
|
||||
class PasswordChange(auth_views.PasswordChangeView):
|
||||
template_name = 'registration/password_change.html'
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse_lazy('profile_detail', kwargs={'pk': self.request.user.id})
|
||||
|
||||
|
||||
class Index(LoginRequiredMixin, generic.TemplateView):
|
||||
template_name = 'index.html'
|
||||
|
||||
|
||||
class AssetList(LoginRequiredMixin, generic.ListView):
|
||||
model = models.Asset
|
||||
template_name = 'asset_list.html'
|
||||
paginate_by = 40
|
||||
ordering = ['-pk']
|
||||
|
||||
|
||||
class AssetDetail(LoginRequiredMixin, generic.DetailView):
|
||||
model = models.Asset
|
||||
template_name = 'asset_update.html'
|
||||
|
||||
|
||||
# class AssetCreate(LoginRequiredMixin, generic.TemplateView):
|
||||
# fields = '__all__'
|
||||
# template_name = 'asset_update.html'
|
||||
# # success_url = reverse_lazy('asset_list')
|
||||
|
||||
|
||||
class AssetEdit(LoginRequiredMixin, generic.TemplateView):
|
||||
template_name = 'asset_update.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(AssetEdit, self).get_context_data(**kwargs)
|
||||
if self.kwargs:
|
||||
context['object'] = get_object_or_404(models.Asset, pk=self.kwargs['pk'])
|
||||
context['form'] = forms.AssetForm
|
||||
# context['asset_names'] = models.Asset.objects.values_list('asset_id', 'description').order_by('-date_acquired')[]
|
||||
|
||||
if self.request.GET.get('duplicate'):
|
||||
context['duplicate'] = True
|
||||
context['previous_asset_id'] = context['object'].asset_id
|
||||
context['previous_asset_pk'] = context['object'].pk
|
||||
context['object'].pk = 0
|
||||
context['object'].asset_id = ''
|
||||
context['object'].serial_number = ''
|
||||
else:
|
||||
context['edit'] = True
|
||||
|
||||
return context
|
||||
|
||||
|
||||
@login_required()
|
||||
def asset_update(request):
|
||||
context = dict()
|
||||
|
||||
if request.method == 'POST' and request.is_ajax():
|
||||
defaults = QueryDict(request.POST['form'].encode('ASCII')).dict()
|
||||
defaults.pop('csrfmiddlewaretoken')
|
||||
|
||||
asset_pk = int(defaults.pop('id'))
|
||||
|
||||
if defaults['date_acquired']:
|
||||
defaults['date_acquired'] = parser.parse(defaults.pop('date_acquired'))
|
||||
else:
|
||||
defaults['date_acquired'] = None
|
||||
|
||||
if defaults['date_sold']:
|
||||
defaults['date_sold'] = parser.parse(defaults.pop('date_sold'))
|
||||
else:
|
||||
defaults['date_sold'] = None
|
||||
|
||||
# if defaults['parent']:
|
||||
# defaults['parent'] = models.Asset.objects.get(asset_id=defaults.pop('parent'))
|
||||
|
||||
form = forms.AssetForm(defaults)
|
||||
context['valid'] = form.is_valid()
|
||||
context['errors'] = form.errors.as_json()
|
||||
|
||||
if asset_pk == 0:
|
||||
asset = models.Asset.objects.create(**form.cleaned_data)
|
||||
else:
|
||||
asset, created = models.Asset.objects.update_or_create(pk=asset_pk, defaults=form.cleaned_data)
|
||||
|
||||
context['url'] = reverse('asset_detail', args=[asset.pk])
|
||||
|
||||
return HttpResponse(json.dumps(context), content_type='application/json')
|
||||
|
||||
|
||||
@login_required()
|
||||
def asset_delete(request):
|
||||
context = dict()
|
||||
if request.method == 'POST' and request.is_ajax():
|
||||
asset = get_object_or_404(models.Asset, pk=request.POST.get('asset_id', None))
|
||||
asset.delete()
|
||||
|
||||
context['url'] = reverse('asset_list')
|
||||
|
||||
return HttpResponse(json.dumps(context), content_type='application/json')
|
||||
|
||||
|
||||
@login_required()
|
||||
def asset_filter(request):
|
||||
context = dict()
|
||||
|
||||
if request.method == 'POST' and request.is_ajax():
|
||||
defaults = QueryDict(request.POST['form'].encode('ASCII')).dict()
|
||||
defaults.pop('csrfmiddlewaretoken')
|
||||
|
||||
context['object_list'] = models.Asset.objects.filter(
|
||||
Q(pk__icontains=defaults.get('asset_id')) |
|
||||
Q(asset_id__icontains=defaults.get('asset_id'))
|
||||
)
|
||||
|
||||
if request.POST.get('sender', None) == 'asset_update':
|
||||
return render(request, template_name='asset_update_search_results.html', context=context)
|
||||
else:
|
||||
return render(request, template_name='asset_list_table_body.html', context=context)
|
||||
|
||||
|
||||
class SupplierList(generic.ListView):
|
||||
model = models.Supplier
|
||||
template_name = 'supplier_list.html'
|
||||
paginate_by = 40
|
||||
ordering = ['name']
|
||||
|
||||
|
||||
class SupplierDetail(generic.DetailView):
|
||||
model = models.Supplier
|
||||
template_name = 'supplier_detail.html'
|
||||
|
||||
|
||||
class SupplierCreate(generic.CreateView):
|
||||
model = models.Supplier
|
||||
form_class = forms.SupplierForm
|
||||
template_name = 'supplier_update.html'
|
||||
|
||||
|
||||
class SupplierUpdate(generic.UpdateView):
|
||||
model = models.Supplier
|
||||
form_class = forms.SupplierForm
|
||||
template_name = 'supplier_update.html'
|
||||
Reference in New Issue
Block a user