initial commit

This commit is contained in:
Pawel Kowalski 2018-08-06 23:26:23 +02:00
commit 5dbef5a694
119 changed files with 20967 additions and 0 deletions

39
.gitignore vendored Normal file
View File

@ -0,0 +1,39 @@
.DS_Store
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
dist/
server/static/
t.*
# C extensions
*.so
# client
node_modules
# Envs
.env
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.swp
# Backend
staticfiles
schema.json
# Wagtail assets
server/documents
server/images
server/original_images
images/
original_images/
server/media/

29
Pipfile Normal file
View File

@ -0,0 +1,29 @@
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"
[dev-packages]
awscli = "*"
ipdb = "*"
[packages]
factory-boy = "*"
wagtail_factories = {git = "https://github.com/mvantellingen/wagtail-factories.git", ref = "master"}
django = "==2.0.6"
whitenoise = "==4.0b4"
"psycopg2" = "==2.7.3.2"
gunicorn = "==19.7.1"
python-dotenv = "==0.7.1"
dj-database-url = "==0.4.1"
raven = "==6.3.0"
django-extensions = "==1.9.8"
graphene-django = "==2.0.0"
django-filter = "==2.0.0.dev1"
pillow = "==5.0.0"
wagtail = "==2.1"
django-cors-headers = "==2.2.0"
django-storages = "*"
"boto3" = "*"
django-compressor = "*"
django-libsass = "*"

734
Pipfile.lock generated Normal file
View File

@ -0,0 +1,734 @@
{
"_meta": {
"hash": {
"sha256": "6a729468480cd51f53f689939028a6ee889ac501e52a6b11c2efc6083c396e99"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"name": "pypi",
"url": "https://pypi.python.org/simple",
"verify_ssl": true
}
]
},
"default": {
"aniso8601": {
"hashes": [
"sha256:7849749cf00ae0680ad2bdfe4419c7a662bef19c03691a19e008c8b9a5267802",
"sha256:94f90871fcd314a458a3d4eca1c84448efbd200e86f55fe4c733c7a40149ef50"
],
"version": "==3.0.2"
},
"beautifulsoup4": {
"hashes": [
"sha256:11a9a27b7d3bddc6d86f59fb76afb70e921a25ac2d6cc55b40d072bd68435a76",
"sha256:7015e76bf32f1f574636c4288399a6de66ce08fb7b2457f628a8d70c0fbabb11",
"sha256:808b6ac932dccb0a4126558f7dfdcf41710dd44a4ef497a0bb59a77f9f078e89"
],
"version": "==4.6.0"
},
"boto3": {
"hashes": [
"sha256:5fcbfea71d7bf818ffc51a380b53899502b7046ca6ba52cca9c44bbfe20bb275",
"sha256:7ba18f6edb603db7ef77733427f6f76a300aab217a9259649ddc91d4521b226f"
],
"index": "pypi",
"version": "==1.7.45"
},
"botocore": {
"hashes": [
"sha256:62519fe407354052befda5f928b988c9059a56292e75dba9d0fac31d9344e279",
"sha256:e62645374cbb01f65324fe479c2a389b414344db96db2f62b0f8a55701fe3416"
],
"version": "==1.10.45"
},
"certifi": {
"hashes": [
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
],
"version": "==2018.4.16"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"version": "==3.0.4"
},
"click": {
"hashes": [
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
],
"version": "==6.7"
},
"dj-database-url": {
"hashes": [
"sha256:7f4c78d2a090df8dfaf56d5d3ff7bbee17360436e4879558317e2314424864cd"
],
"index": "pypi",
"version": "==0.4.1"
},
"django": {
"hashes": [
"sha256:3eb25c99df1523446ec2dc1b00e25eb2ecbdf42c9d8b0b8b32a204a8db9011f8",
"sha256:69ff89fa3c3a8337015478a1a0744f52a9fef5d12c1efa01a01f99bcce9bf10c"
],
"index": "pypi",
"version": "==2.0.6"
},
"django-appconf": {
"hashes": [
"sha256:6a4d9aea683b4c224d97ab8ee11ad2d29a37072c0c6c509896dd9857466fb261",
"sha256:ddab987d14b26731352c01ee69c090a4ebfc9141ed223bef039d79587f22acd9"
],
"version": "==1.0.2"
},
"django-compressor": {
"hashes": [
"sha256:7732676cfb9d58498dfb522b036f75f3f253f72ea1345ac036434fdc418c2e57",
"sha256:9616570e5b08e92fa9eadc7a1b1b49639cce07ef392fc27c74230ab08075b30f"
],
"index": "pypi",
"version": "==2.2"
},
"django-cors-headers": {
"hashes": [
"sha256:0e9532628b3aa8806442d4d0b15e56112e6cfbef3735e13401935c98b842a2b4",
"sha256:c7ec4816ec49416517b84f317499d1519db62125471922ab78d670474ed9b987"
],
"index": "pypi",
"version": "==2.2.0"
},
"django-extensions": {
"hashes": [
"sha256:7776b6c5f3807997c1459e96f4eed4af2b571fd6bebf61462242fa957166df30",
"sha256:9f1c314cfd4b974f03c5589f46f33051aa1d6b5a38cfb7f8824f59e9337768ae"
],
"index": "pypi",
"version": "==1.9.8"
},
"django-filter": {
"hashes": [
"sha256:57c12c8ed40861e8ec7219ea65adcdd92ed0ea4c5b76a86f9ff9216a80dd5af7",
"sha256:57c5507b0011058a7f2d2227b7ef9fea27e69e53ef65da6d2fbd0b27cdaafed3"
],
"index": "pypi",
"version": "==2.0.0.dev1"
},
"django-libsass": {
"hashes": [
"sha256:49db3334b87e1f7955c4f9fb9945bc296f8bfd27a14d6d89706e4b0e5dc5de1c"
],
"index": "pypi",
"version": "==0.7"
},
"django-modelcluster": {
"hashes": [
"sha256:2a6c0638ba295d44fc316c42b6da20509b186fe3500c674539441d451de5abfe"
],
"version": "==4.1"
},
"django-storages": {
"hashes": [
"sha256:7339070cf0c8042f5a885783a0a909175a8dbb68e7f5697d597571c830a460c4",
"sha256:f1dd5668a4df9a23aff56c8321ea3aac3fda23d9d17473158d308d1b13e5363e"
],
"index": "pypi",
"version": "==1.6.6"
},
"django-taggit": {
"hashes": [
"sha256:58aa3e59e0643446e102523f22d137300298e2a537b1c5b0c310d99143f2c2b8",
"sha256:fd13e304ba37ff09e601c4797d893fb7d3e699a789b5afb0b09d686f94470441"
],
"version": "==0.22.2"
},
"django-treebeard": {
"hashes": [
"sha256:c21db06a8d4943bf2a28d9d7a119058698fb76116df2679ecbf15a46a501de42"
],
"version": "==4.3"
},
"djangorestframework": {
"hashes": [
"sha256:b6714c3e4b0f8d524f193c91ecf5f5450092c2145439ac2769711f7eba89a9d9",
"sha256:c375e4f95a3a64fccac412e36fb42ba36881e52313ec021ef410b40f67cddca4"
],
"version": "==3.8.2"
},
"docutils": {
"hashes": [
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
],
"version": "==0.14"
},
"draftjs-exporter": {
"hashes": [
"sha256:d2ceeef98185ba02355496851aee17d25951f5d8c72c12f8af6c186e312e9598"
],
"version": "==2.1.2"
},
"factory-boy": {
"hashes": [
"sha256:6f25cc4761ac109efd503f096e2ad99421b1159f01a29dbb917359dcd68e08ca",
"sha256:d552cb872b310ae78bd7429bf318e42e1e903b1a109e899a523293dfa762ea4f"
],
"index": "pypi",
"version": "==2.11.1"
},
"faker": {
"hashes": [
"sha256:04645d946256b835c675c1cef7c03817a164b0c4e452018fd50b212ddff08c22",
"sha256:fe48f35aa3443bc5655b0782d3a2f594bf4882d0e2a947b80207a60494d32907"
],
"version": "==0.8.16"
},
"graphene": {
"hashes": [
"sha256:8fd8e6195c56c15b2936e7dee2e156692eba4752ee1978f65e10925eafe8d014",
"sha256:98e74c32d0415e5b5362738c1c1cb4b7a4e411b5d3d828abb29ccd3efb378c44"
],
"version": "==2.1.2"
},
"graphene-django": {
"hashes": [
"sha256:5cabf46b59f242a533fe1df1912c87d5ad6606246937609be2e6c9086cfdf7a4",
"sha256:70d9358bc48c806b6a9458e8344f0a1211cd1f1ef923a092aa55e6bcacc2c3fc"
],
"index": "pypi",
"version": "==2.0.0"
},
"graphql-core": {
"hashes": [
"sha256:4830699be53f9154273fa15726fc8b0c90bc22bbb8fc7c932586503b3cb9330e",
"sha256:539355351343dede3ecb771e0d273a1b72405cb6d64f45bb8f92ecc4d7109af0"
],
"version": "==2.0"
},
"graphql-relay": {
"hashes": [
"sha256:2716b7245d97091af21abf096fabafac576905096d21ba7118fba722596f65db"
],
"version": "==0.4.5"
},
"gunicorn": {
"hashes": [
"sha256:75af03c99389535f218cc596c7de74df4763803f7b63eb09d77e92b3956b36c6",
"sha256:eee1169f0ca667be05db3351a0960765620dad53f53434262ff8901b68a1b622"
],
"index": "pypi",
"version": "==19.7.1"
},
"html5lib": {
"hashes": [
"sha256:20b159aa3badc9d5ee8f5c647e5efd02ed2a66ab8d354930bd9ff139fc1dc0a3",
"sha256:66cb0dcfdbbc4f9c3ba1a63fdb511ffdbd4f513b2b6d81b80cd26ce6b3fb3736"
],
"version": "==1.0.1"
},
"idna": {
"hashes": [
"sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
"sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
],
"version": "==2.7"
},
"iso8601": {
"hashes": [
"sha256:210e0134677cc0d02f6028087fee1df1e1d76d372ee1db0bf30bf66c5c1c89a3",
"sha256:49c4b20e1f38aa5cf109ddcd39647ac419f928512c869dc01d5c7098eddede82",
"sha256:bbbae5fb4a7abfe71d4688fd64bff70b91bbd74ef6a99d964bab18f7fdf286dd"
],
"version": "==0.1.12"
},
"jmespath": {
"hashes": [
"sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64",
"sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63"
],
"version": "==0.9.3"
},
"l18n": {
"hashes": [
"sha256:a72b9a80b297da5bc807f347bfa61aa9900c35bf1bb55e61a17ec7e58d9e0de7"
],
"version": "==2016.6.4"
},
"libsass": {
"hashes": [
"sha256:0f2e421d3e5a53833243e0a5f2cf7ebe9812725a7f27a797c38f3c7190ce2a82",
"sha256:1b74aff85f1560d629a070552ec67f9f0ff9a47446ffafddafad9944f7589ae1",
"sha256:1cf80c04a77d36fd77f00b1ae0a269eee780d971fabd9d493b15d30de9857ae5",
"sha256:1d55dfe8e91a15a7d72d7f8aca16e74da36899e70d911af66d7184f1c82e2b39",
"sha256:23755425149fe0f576fd0ab7bcd151fe09400b2d980fe176c28f6c19e053c830",
"sha256:4a434d5b713b97c4141fb71c59341d4ebff8669114b14c626af51e145a48710e",
"sha256:4dcd5b546bed977276f97eb7a2a13cb7cbf0a38d672e7b5525b7587c8cabcf27",
"sha256:62771c8ead9227579891814dd714be645243741aa23e5cb232ac0c245cf29a37",
"sha256:727fb84326ffa930bc09fad8b706e77ada4d13b3adf35cce134962a434d7eccb",
"sha256:7b9e7179b5f4fc32bc716f86e9ccaeb48ab90e7eb6648b339440346733af8828",
"sha256:a0ffca466b35fb57f2afe1f1c5fd39b4c51a4107596d28ef8c0d3bb0962244b5",
"sha256:cbd5ee83d3603a2b2c2937d8f06acc07b30fd22642ea2460c966d4fd6217f1d0",
"sha256:de1eae502764b3dde294d6652a0046489cf31008de190c4dd8d05e7f4b5e0d71",
"sha256:e00b6c6d75a6e912990cbc23d48ddfdbfefc3e400c20be6593988839292248c5",
"sha256:ed8beef197efc6e6ab0ad03cea0885b31cc11f226290783649b4dafe1fb2ea27"
],
"version": "==0.14.5"
},
"pillow": {
"hashes": [
"sha256:0013f590a8f260df60bcfd65db19d18efc04e7f046c3c82a40e2e2b3292a937c",
"sha256:0b899ee80920bb533f26581af9b4660bc12aff4562555afe74e429101ebf3c94",
"sha256:12f29d6c23424f704c66b5b68c02fe0b571504459605cfe36ab8158359b0e1bb",
"sha256:135e9aa65150c53f7db85bf2bebb8a0e1a48ea850e80cf66e16dd04fa09d309c",
"sha256:153ec6f18f7b61641e0e6e502acfaf4a06c9aba2ea11c0b4b3578ea9f13a4a4a",
"sha256:17fe25efc785194d48c38fad85dce470013ba19d2fb66639e149f14bccf1327f",
"sha256:1912b7230459fd53682dae32b83cbd8e5d642ba36d4be18566f00a9c063aa13d",
"sha256:1a5b93084e01328a1cb1ecdad99d11d75e881e89a95f88d85b523646553b36c2",
"sha256:25193f934d37d836a6b1f4c062ce574a96cbca7c6d9dc8ddfbbac7f9c54deaa4",
"sha256:2c042352b430d678db50c78c5214e19638eff8b688941271da2de21fd298dfe5",
"sha256:2e818dbe445e86fc6c266973fe540c35125c42eb2cf13a6095e9adaa89c0deb5",
"sha256:2fcde9954c8882d1c7f93bb828caa34a4c5e3ee69dbc7895dc8652ad972b455a",
"sha256:35f7d998b8e82fb3fb51ff88b30485eb81cd7dd56ec7e1a8deba23eb88532d44",
"sha256:37cc0339abfa9e295c75d9a7f227d35cb44716feb95057f9449c4a9e9a17daf7",
"sha256:43334f9581cd067945b8898cef9eb5714ee4883f8de0304c011f1dbdb1d4e2aa",
"sha256:4bd4a71501b6d51db4abc07e1f43f5a6fed0a1a9583cca0b401d6af50284b0db",
"sha256:57aa6198ba8acba1313c3b743e267d821a60cac77e6026caf0b55ca58d3d23be",
"sha256:5b0d657460d9f3615876fec6306e97ca15a471f6169b622d76a47e270998acf1",
"sha256:5cd36804f9f06a914a883fe682df5711d16d7b4f44d43189c5f013e7cd91e149",
"sha256:6977cf073d83358b34f93abf5c1f1193b88675fe0e4441e0e28318bc3dcba7a0",
"sha256:718ec7a122b28d64afc5fbc3a9b99bb0545ef511373cac06fe7624520e82cb20",
"sha256:7dfbefdb3fb911ca9faed307bf309861e9995e36cca6b761c7ba6d9b77a9744a",
"sha256:801cca8923508311bf5d6d0f7da5362552e8208ebd8ec0d7b9f2cd2ff5705734",
"sha256:82b172e3264e62372c01b5b009b5b1a02fbb9276cbe5cc57ab00a6d6e5ed9a18",
"sha256:82d1ff571489765df2816785d532e243bde213752156c227fca595723ec5ff42",
"sha256:8580fc58074a16b749905b26cf8363f7b628dd167ba0130f5382cdc91c86b509",
"sha256:931030d1d6282b7900e6b0a7ff9ecdb503b5e1e6781800dab2b71a9f39405bff",
"sha256:9525cd680a6f9e80c6c0af03cf973e6505c59f60b4745f682cd1a449e54b31bb",
"sha256:a224651a81e45ef4f1d0164e256c5f6b4abb49f2ae8f22ba2f3a9d0ff338e608",
"sha256:a370d1c570f1d72e877099651e752332444b1c5009381f043c9da5fd47f3ebae",
"sha256:b1d33c63a55d0d85df0ad02b2c16158fb4d8153afa7b908f1a67330fac694cd6",
"sha256:b2240f298482f823576f397bb9f32ea913ad9456c526e141bc6f0a022b37a3e8",
"sha256:b85f703c2ffe539313e39ce0676bed0f355cec45a16e58c9ab7417445843047c",
"sha256:b9f63451084a718eccdeb1e382768c94647915653af4d6019f64560d9e98642b",
"sha256:c793dfaa130847ccff958492b76ae8b9304e60b8a79a92962cb19e368276a22b",
"sha256:d60c1625b108432ace8b1fa1a584017e5efa73f107d0f493c7f39c79bebf1d41",
"sha256:dc4b018d5c9b636f7546583c5591b9ea00c328c3e5871992ef5b95bac353f097",
"sha256:ddd16ab250b4fc97db1c47407e78c25216a75c29d29d10ad37e51b7a2ec7b2c3",
"sha256:e126ff4fed71e78333840c07279e1617f63cfca76d63ad5b27d65a7277206a3d",
"sha256:f8d49be8c282df8d2e1ab6ab53ab8abd859b1fa6fed384457ee85c9eff64ef97",
"sha256:fcf64c91fd44485100a2965d23bb0e227d093e91f7e776c5ca3b32574766eb56"
],
"index": "pypi",
"version": "==5.0.0"
},
"promise": {
"hashes": [
"sha256:0bca4ed933e3d50e3d18fb54fc1432fa84b0564838cd093e824abcd718ab9304",
"sha256:95506bac89df7a495e0b8c813fd782dd1ae590decb52f95248e316c6659ca49b"
],
"version": "==2.1"
},
"psycopg2": {
"hashes": [
"sha256:009e0bc09a57dbef4b601cb8b46a2abad51f5274c8be4bba276ff2884cd4cc53",
"sha256:0344b181e1aea37a58c218ccb0f0f771295de9aa25a625ed076e6996c6530f9e",
"sha256:0cd4c848f0e9d805d531e44973c8f48962e20eb7fc0edac3db4f9dbf9ed5ab82",
"sha256:1286dd16d0e46d59fa54582725986704a7a3f3d9aca6c5902a7eceb10c60cb7e",
"sha256:1cf5d84290c771eeecb734abe2c6c3120e9837eb12f99474141a862b9061ac51",
"sha256:207ba4f9125a0a4200691e82d5eee7ea1485708eabe99a07fc7f08696fae62f4",
"sha256:25250867a4cd1510fb755ef9cb38da3065def999d8e92c44e49a39b9b76bc893",
"sha256:2954557393cfc9a5c11a5199c7a78cd9c0c793a047552d27b1636da50d013916",
"sha256:317612d5d0ca4a9f7e42afb2add69b10be360784d21ce4ecfbca19f1f5eadf43",
"sha256:37f54452c7787dbdc0a634ca9773362b91709917f0b365ed14b831f03cbd34ba",
"sha256:40fa5630cd7d237cd93c4d4b64b9e5ed9273d1cfce55241c7f9066f5db70629d",
"sha256:57baf63aeb2965ca4b52613ce78e968b6d2bde700c97f6a7e8c6c236b51ab83e",
"sha256:594aa9a095de16614f703d759e10c018bdffeafce2921b8e80a0e8a0ebbc12e5",
"sha256:5c3213be557d0468f9df8fe2487eaf2990d9799202c5ff5cb8d394d09fad9b2a",
"sha256:697ff63bc5451e0b0db48ad205151123d25683b3754198be7ab5fcb44334e519",
"sha256:6c2f1a76a9ebd9ecf7825b9e20860139ca502c2bf1beabf6accf6c9e66a7e0c3",
"sha256:7a75565181e75ba0b9fb174b58172bf6ea9b4331631cfe7bafff03f3641f5d73",
"sha256:7a9c6c62e6e05df5406e9b5235c31c376a22620ef26715a663cee57083b3c2ea",
"sha256:7c31dade89634807196a6b20ced831fbd5bec8a21c4e458ea950c9102c3aa96f",
"sha256:82c40ea3ac1555e0462803380609fbe8b26f52620f3d4f8eb480cfd8ceed8a14",
"sha256:8f5942a4daf1ffac42109dc4a72f786af4baa4fa702ede1d7c57b4b696c2e7d6",
"sha256:92179bd68c2efe72924a99b6745a9172471931fc296f9bfdf9645b75eebd6344",
"sha256:94e4128ba1ea56f02522fffac65520091a9de3f5c00da31539e085e13db4771b",
"sha256:988d2ec7560d42ef0ac34b3b97aad14c4f068792f00e1524fa1d3749fe4e4b64",
"sha256:9d6266348b15b4a48623bf4d3e50445d8e581da413644f365805b321703d0fac",
"sha256:9d64fed2681552ed642e9c0cc831a9e95ab91de72b47d0cb68b5bf506ba88647",
"sha256:b9358e203168fef7bfe9f430afaed3a2a624717a1d19c7afa7dfcbd76e3cd95c",
"sha256:bf708455cd1e9fa96c05126e89a0c59b200d086c7df7bbafc7d9be769e4149a3",
"sha256:d3ac07240e2304181ffdb13c099840b5eb555efc7be9344503c0c03aa681de79",
"sha256:ddca39cc55877653b5fcf59976d073e3d58c7c406ef54ae8e61ddf8782867182",
"sha256:fc993c9331d91766d54757bbc70231e29d5ceb2d1ac08b1570feaa0c38ab9582"
],
"index": "pypi",
"version": "==2.7.3.2"
},
"python-dateutil": {
"hashes": [
"sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0",
"sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8"
],
"markers": "python_version >= '2.7'",
"version": "==2.7.3"
},
"python-dotenv": {
"hashes": [
"sha256:45e927c34204c90f5faa35ea8709b894f6b1a7712d77eb50940601068040993b",
"sha256:dc7940052cfe170e881aea40feb4ea7776e6a97170ed038fd2ee7e26e47585f2"
],
"index": "pypi",
"version": "==0.7.1"
},
"pytz": {
"hashes": [
"sha256:65ae0c8101309c45772196b21b74c46b2e5d11b6275c45d251b150d5da334555",
"sha256:c06425302f2cf668f1bba7a0a03f3c1d34d4ebeef2c72003da308b3947c7f749"
],
"version": "==2018.4"
},
"raven": {
"hashes": [
"sha256:cb644fb12ee886a341041dcd533540dfc82619a50bf0b7c587af070054bd2c7f",
"sha256:f3e465a545dcdb6a387d1fcb199d08f786ba3732d7ce6aa681718b04da6aedf1"
],
"index": "pypi",
"version": "==6.3.0"
},
"rcssmin": {
"hashes": [
"sha256:ca87b695d3d7864157773a61263e5abb96006e9ff0e021eff90cbe0e1ba18270"
],
"version": "==1.0.6"
},
"requests": {
"hashes": [
"sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1",
"sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a"
],
"version": "==2.19.1"
},
"rjsmin": {
"hashes": [
"sha256:dd9591aa73500b08b7db24367f8d32c6470021f39d5ab4e50c7c02e4401386f1"
],
"version": "==1.0.12"
},
"rx": {
"hashes": [
"sha256:13a1d8d9e252625c173dc795471e614eadfe1cf40ffc684e08b8fff0d9748c23",
"sha256:7357592bc7e881a95e0c2013b73326f704953301ab551fbc8133a6fadab84105"
],
"version": "==1.6.1"
},
"s3transfer": {
"hashes": [
"sha256:90dc18e028989c609146e241ea153250be451e05ecc0c2832565231dacdf59c1",
"sha256:c7a9ec356982d5e9ab2d4b46391a7d6a950e2b04c472419f5fdec70cc0ada72f"
],
"version": "==0.1.13"
},
"singledispatch": {
"hashes": [
"sha256:5b06af87df13818d14f08a028e42f566640aef80805c3b50c5056b086e3c2b9c",
"sha256:833b46966687b3de7f438c761ac475213e53b306740f1abfaa86e1d1aae56aa8"
],
"version": "==3.4.0.3"
},
"six": {
"hashes": [
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
],
"version": "==1.11.0"
},
"text-unidecode": {
"hashes": [
"sha256:5a1375bb2ba7968740508ae38d92e1f889a0832913cb1c447d5e2046061a396d",
"sha256:801e38bd550b943563660a91de8d4b6fa5df60a542be9093f7abf819f86050cc"
],
"version": "==1.2"
},
"typing": {
"hashes": [
"sha256:3a887b021a77b292e151afb75323dea88a7bc1b3dfa92176cff8e44c8b68bddf",
"sha256:b2c689d54e1144bbcfd191b0832980a21c2dbcf7b5ff7a66248a60c90e951eb8",
"sha256:d400a9344254803a2368533e4533a4200d21eb7b6b729c173bc38201a74db3f2"
],
"version": "==3.6.4"
},
"unidecode": {
"hashes": [
"sha256:280a6ab88e1f2eb5af79edff450021a0d3f0448952847cd79677e55e58bad051",
"sha256:61f807220eda0203a774a09f84b4304a3f93b5944110cc132af29ddb81366883"
],
"version": "==0.4.21"
},
"urllib3": {
"hashes": [
"sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf",
"sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5"
],
"version": "==1.23"
},
"wagtail": {
"hashes": [
"sha256:3cdaa2901e566688258ace14963c42e8f35e264a5a7c937fd99b7a17a867dee2",
"sha256:97fe49eba863b7b4a0ec671e6feada30dbb35cbcc339f2eac4a770d5e21250ad"
],
"index": "pypi",
"version": "==2.1"
},
"wagtail-factories": {
"git": "https://github.com/mvantellingen/wagtail-factories.git",
"ref": "master"
},
"webencodings": {
"hashes": [
"sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78",
"sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"
],
"version": "==0.5.1"
},
"whitenoise": {
"hashes": [
"sha256:9a8ef48d2a2b4a101d84a0e5edbb20759affbc832cd74f3194e803cca7f28f6a",
"sha256:c42d640b8db482924b36ddadcc7087cf49f796fa1faa1583b3d07118f55a4265"
],
"index": "pypi",
"version": "==4.0b4"
},
"willow": {
"hashes": [
"sha256:76a8874304356b7d86923405f5ca1df125c3540fb55b32747e7a33ba59bc1744",
"sha256:818ee11803c90a0a6d49c94b0453d6266be1ef83ae00de72731c45fae4d3e78c"
],
"version": "==1.1"
}
},
"develop": {
"appnope": {
"hashes": [
"sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0",
"sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"
],
"markers": "sys_platform == 'darwin'",
"version": "==0.1.0"
},
"awscli": {
"hashes": [
"sha256:a5d471074d957b9ab3feb830be4c4f8a1e1309c4d3d03f572b2a20b674d5394e",
"sha256:cd4d680212d9d901c0cfcc0436b137a147e43faae630fda359eb88d6fd9392b2"
],
"index": "pypi",
"version": "==1.15.45"
},
"backcall": {
"hashes": [
"sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4",
"sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"
],
"version": "==0.1.0"
},
"botocore": {
"hashes": [
"sha256:62519fe407354052befda5f928b988c9059a56292e75dba9d0fac31d9344e279",
"sha256:e62645374cbb01f65324fe479c2a389b414344db96db2f62b0f8a55701fe3416"
],
"version": "==1.10.45"
},
"colorama": {
"hashes": [
"sha256:463f8483208e921368c9f306094eb6f725c6ca42b0f97e313cb5d5512459feda",
"sha256:48eb22f4f8461b1df5734a074b57042430fb06e1d61bd1e11b078c0fe6d7a1f1"
],
"version": "==0.3.9"
},
"decorator": {
"hashes": [
"sha256:2c51dff8ef3c447388fe5e4453d24a2bf128d3a4c32af3fabef1f01c6851ab82",
"sha256:c39efa13fbdeb4506c476c9b3babf6a718da943dab7811c206005a4a956c080c"
],
"version": "==4.3.0"
},
"docutils": {
"hashes": [
"sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
"sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
"sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
],
"version": "==0.14"
},
"ipdb": {
"hashes": [
"sha256:7081c65ed7bfe7737f83fa4213ca8afd9617b42ff6b3f1daf9a3419839a2a00a"
],
"index": "pypi",
"version": "==0.11"
},
"ipython": {
"hashes": [
"sha256:a0c96853549b246991046f32d19db7140f5b1a644cc31f0dc1edc86713b7676f",
"sha256:eca537aa61592aca2fef4adea12af8e42f5c335004dfa80c78caf80e8b525e5c"
],
"version": "==6.4.0"
},
"ipython-genutils": {
"hashes": [
"sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8",
"sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"
],
"version": "==0.2.0"
},
"jedi": {
"hashes": [
"sha256:1972f694c6bc66a2fac8718299e2ab73011d653a6d8059790c3476d2353b99ad",
"sha256:5861f6dc0c16e024cbb0044999f9cf8013b292c05f287df06d3d991a87a4eb89"
],
"version": "==0.12.0"
},
"jmespath": {
"hashes": [
"sha256:6a81d4c9aa62caf061cb517b4d9ad1dd300374cd4706997aff9cd6aedd61fc64",
"sha256:f11b4461f425740a1d908e9a3f7365c3d2e569f6ca68a2ff8bc5bcd9676edd63"
],
"version": "==0.9.3"
},
"parso": {
"hashes": [
"sha256:cdef26e8adc10d589f3ec4eb444bd0a29f3f1eb6d72a4292ab8afcb9d68976a6",
"sha256:f0604a40b96e062b0fd99cf134cc2d5cdf66939d0902f8267d938b0d5b26707f"
],
"version": "==0.2.1"
},
"pexpect": {
"hashes": [
"sha256:2a8e88259839571d1251d278476f3eec5db26deb73a70be5ed5dc5435e418aba",
"sha256:3fbd41d4caf27fa4a377bfd16fef87271099463e6fa73e92a52f92dfee5d425b"
],
"markers": "sys_platform != 'win32'",
"version": "==4.6.0"
},
"pickleshare": {
"hashes": [
"sha256:84a9257227dfdd6fe1b4be1319096c20eb85ff1e82c7932f36efccfe1b09737b",
"sha256:c9a2541f25aeabc070f12f452e1f2a8eae2abd51e1cd19e8430402bdf4c1d8b5"
],
"version": "==0.7.4"
},
"prompt-toolkit": {
"hashes": [
"sha256:1df952620eccb399c53ebb359cc7d9a8d3a9538cb34c5a1344bdbeb29fbcc381",
"sha256:3f473ae040ddaa52b52f97f6b4a493cfa9f5920c255a12dc56a7d34397a398a4",
"sha256:858588f1983ca497f1cf4ffde01d978a3ea02b01c8a26a8bbc5cd2e66d816917"
],
"version": "==1.0.15"
},
"ptyprocess": {
"hashes": [
"sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0",
"sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"
],
"version": "==0.6.0"
},
"pyasn1": {
"hashes": [
"sha256:2f57960dc7a2820ea5a1782b872d974b639aa3b448ac6628d1ecc5d0fe3986f2",
"sha256:3651774ca1c9726307560792877db747ba5e8a844ea1a41feb7670b319800ab3",
"sha256:602fda674355b4701acd7741b2be5ac188056594bf1eecf690816d944e52905e",
"sha256:8fb265066eac1d3bb5015c6988981b009ccefd294008ff7973ed5f64335b0f2d",
"sha256:9334cb427609d2b1e195bb1e251f99636f817d7e3e1dffa150cb3365188fb992",
"sha256:9a15cc13ff6bf5ed29ac936ca941400be050dff19630d6cd1df3fb978ef4c5ad",
"sha256:a66dcda18dbf6e4663bde70eb30af3fc4fe1acb2d14c4867a861681887a5f9a2",
"sha256:ba77f1e8d7d58abc42bfeddd217b545fdab4c1eeb50fd37c2219810ad56303bf",
"sha256:cdc8eb2eaafb56de66786afa6809cd9db2df1b3b595dcb25aa5b9dc61189d40a",
"sha256:d01fbba900c80b42af5c3fe1a999acf61e27bf0e452e0f1ef4619065e57622da",
"sha256:f281bf11fe204f05859225ec2e9da7a7c140b65deccd8a4eb0bc75d0bd6949e0",
"sha256:fb81622d8f3509f0026b0683fe90fea27be7284d3826a5f2edf97f69151ab0fc"
],
"version": "==0.4.3"
},
"pygments": {
"hashes": [
"sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d",
"sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc"
],
"version": "==2.2.0"
},
"python-dateutil": {
"hashes": [
"sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0",
"sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8"
],
"markers": "python_version >= '2.7'",
"version": "==2.7.3"
},
"pyyaml": {
"hashes": [
"sha256:0c507b7f74b3d2dd4d1322ec8a94794927305ab4cebbe89cc47fe5e81541e6e8",
"sha256:16b20e970597e051997d90dc2cddc713a2876c47e3d92d59ee198700c5427736",
"sha256:3262c96a1ca437e7e4763e2843746588a965426550f3797a79fca9c6199c431f",
"sha256:326420cbb492172dec84b0f65c80942de6cedb5233c413dd824483989c000608",
"sha256:4474f8ea030b5127225b8894d626bb66c01cda098d47a2b0d3429b6700af9fd8",
"sha256:592766c6303207a20efc445587778322d7f73b161bd994f227adaa341ba212ab",
"sha256:5ac82e411044fb129bae5cfbeb3ba626acb2af31a8d17d175004b70862a741a7",
"sha256:5f84523c076ad14ff5e6c037fe1c89a7f73a3e04cf0377cb4d017014976433f3",
"sha256:827dc04b8fa7d07c44de11fabbc888e627fa8293b695e0f99cb544fdfa1bf0d1",
"sha256:b4c423ab23291d3945ac61346feeb9a0dc4184999ede5e7c43e1ffb975130ae6",
"sha256:bc6bced57f826ca7cb5125a10b23fd0f2fff3b7c4701d64c439a300ce665fff8",
"sha256:c01b880ec30b5a6e6aa67b09a2fe3fb30473008c85cd6a67359a1b15ed6d83a4",
"sha256:ca233c64c6e40eaa6c66ef97058cdc80e8d0157a443655baa1b2966e812807ca",
"sha256:e863072cdf4c72eebf179342c94e6989c67185842d9997960b3e69290b2fa269"
],
"version": "==3.12"
},
"rsa": {
"hashes": [
"sha256:25df4e10c263fb88b5ace923dd84bf9aa7f5019687b5e55382ffcdb8bede9db5",
"sha256:43f682fea81c452c98d09fc316aae12de6d30c4b5c84226642cf8f8fd1c93abd"
],
"version": "==3.4.2"
},
"s3transfer": {
"hashes": [
"sha256:90dc18e028989c609146e241ea153250be451e05ecc0c2832565231dacdf59c1",
"sha256:c7a9ec356982d5e9ab2d4b46391a7d6a950e2b04c472419f5fdec70cc0ada72f"
],
"version": "==0.1.13"
},
"simplegeneric": {
"hashes": [
"sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173"
],
"version": "==0.8.1"
},
"six": {
"hashes": [
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
],
"version": "==1.11.0"
},
"traitlets": {
"hashes": [
"sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835",
"sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9"
],
"version": "==4.3.2"
},
"wcwidth": {
"hashes": [
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"version": "==0.1.7"
}
}
}

2
Procfile Normal file
View File

@ -0,0 +1,2 @@
release: ./release-tasks.sh
web: gunicorn --log-file=- --pythonpath server core.wsgi

120
README.md Normal file
View File

@ -0,0 +1,120 @@
# skillBox
Sources
* [Django](https://docs.djangoproject.com/en/2.0/)
* [Wagtail](http://docs.wagtail.io/)
* [Graphene](https://github.com/graphql-python/graphene-django)
* [Vue-Apollo](https://github.com/Akryum/vue-apollo)
* [Vuetifyjs](https://vuetifyjs.com/en/getting-started/quick-start)
## Development
### Server
* [Install](https://docs.pipenv.org/#install-pipenv-today) pipenv
* Create virtualenv in install dependencies `pipenv --python 3.6 install --dev`
* Create PostgreSQL database & user
* [Install](https://devcenter.heroku.com/articles/heroku-cli#download-and-install) Heroku cli, run `heroku login` and `heroku git:remote -a caruhome`
* Create .env in `server` file with `SECRET_KEY` and `DATABASE_URL`
* Migrate databases: `pipenv run python manage.py migrate`
* Create super user: `pipenv run python manage.py createsuperuser`
* Run: `pipenv run python manage.py runserver`
* Dummy data: `pipenv run python manage.py dummy_data` (restart the development server afterwards)
#### Notes
* `DEBUG=True` enables the debug middleware http://docs.graphene-python.org/projects/django/en/latest/debug/
### Client
``` bash
# install dependencies
npm install --prefix client
# serve with hot reload at localhost:8080
npm run dev --prefix client
# run storybook
npm run storybook --prefix client
# build
npm run build --prefix client
# build for production with minification
export NODE_ENV=production && npm install --prefix client && npm run build --prefix client
```
After running `npm run dev` login to the Django admin view on the same domain as the webpack dev server is running.
Example: The client runs on localhost:8080 and Django on localhost:8000.
This way you will have a session and a csrf cookie set and the apollo client will
be able to make requests.
Production Build
## Urls
(trailing slashes are required)
* Admin interface: http://127.0.0.1:8000/guru/
* Cms interface: http://127.0.0.1:8000/cms/
* GraphQL Interface: http://localhost:8000/api/graphiql/
## Heroku
`heroku run python server/manage.py <command> --app <appname>`
### Rollabck
After doing a rollback under https://data.heroku.com/
`heroku pg:info --app=<appname>`
Change DATABASE URL (e.g after a rollback)
`heroku pg:promote HEROKU_POSTGRESQL_PINK`
### Backup
`heroku pg:backups:capture --app <appname>`
`heroku pg:backups:url b001 --app <appname>`
## AWS
1. Create user with API Access and add `access key id` and `access key` to `.env` and set `USE_AWS=True`
2. Create S3 Bucket in location EU Ireland
Change bucket `Permissions` / `Bucket Policy`
```
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<bucket-name>/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "<user arn>"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::<bucket-name>/*",
"arn:aws:s3:::<bucket-name>"
]
}
]
}
```

2
bin/post_compile Normal file
View File

@ -0,0 +1,2 @@
# Has to be in post_compile. Heroku release phase won't work :(
python server/manage.py compress

12
client/.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}

9
client/.editorconfig Normal file
View File

@ -0,0 +1,9 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

4
client/.eslintignore Normal file
View File

@ -0,0 +1,4 @@
/build/
/config/
/dist/
/*.js

32
client/.eslintrc.js Normal file
View File

@ -0,0 +1,32 @@
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'indent': 'off',
'semi': 0,
'space-before-function-paren': 'off'
}
}

14
client/.gitignore vendored Normal file
View File

@ -0,0 +1,14 @@
.DS_Store
node_modules/
dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln

10
client/.postcssrc.js Normal file
View File

@ -0,0 +1,10 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}

41
client/build/build.js Normal file
View File

@ -0,0 +1,41 @@
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

View File

@ -0,0 +1,54 @@
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

BIN
client/build/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

101
client/build/utils.js Normal file
View File

@ -0,0 +1,101 @@
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}

View File

@ -0,0 +1,22 @@
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

View File

@ -0,0 +1,97 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json', '.gql', '.graphql'],
alias: {
'@': resolve('src'),
styles: resolve('styles')
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(gql|graphql)$/,
loader: 'graphql-tag/loader',
exclude: /node_modules/
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}

View File

@ -0,0 +1,95 @@
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})

View File

@ -0,0 +1,145 @@
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig

7
client/config/dev.env.js Normal file
View File

@ -0,0 +1,7 @@
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

75
client/config/index.js Normal file
View File

@ -0,0 +1,75 @@
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}

View File

@ -0,0 +1,4 @@
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

24
client/index.html Normal file
View File

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>skillBox</title>
<link href='https://fonts.googleapis.com/css?family=Material+Icons' rel="stylesheet" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Montserrat:500,700" rel="stylesheet">
<style>
body{background:#fafafa;}.center{position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}.lds-dual-ring{display:inline-block;width:64px;height:64px}.lds-dual-ring:after{content:" ";display:block;width:46px;height:46px;margin:1px;border-radius:50%;border:5px solid #FD6E22;border-color:#FD6E22 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}
</style>
</head>
<body>
<div id="app">
<div class="center">
<div class="lds-dual-ring"></div>
</div>
</div>
<!-- built files will be auto injected -->
</body>
</html>

11721
client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

88
client/package.json Normal file
View File

@ -0,0 +1,88 @@
{
"name": "frontend",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "maersu <me@maersu.ch>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"apollo-cache-inmemory": "^1.2.2",
"apollo-client": "^2.3.2",
"apollo-link-http": "^1.5.4",
"appolo": "^6.0.19",
"autoprefixer": "^7.1.2",
"axios": "^0.18.0",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"graphql": "^0.13.2",
"graphql-tag": "^2.9.2",
"html-webpack-plugin": "^2.30.1",
"lodash": "^4.17.10",
"node-notifier": "^5.1.2",
"node-sass": "^4.9.0",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass-loader": "^7.0.3",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"uuid": "^3.2.1",
"vue": "^2.5.2",
"vue-apollo": "^3.0.0-beta.16",
"vue-axios": "^2.1.1",
"vue-loader": "^14.2.1",
"vue-router": "^3.0.1",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"vue-vimeo-player": "0.0.6",
"vuetify": "^1.1.8",
"vuex": "^3.0.1",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"devDependencies": {}
}

50
client/src/App.vue Normal file
View File

@ -0,0 +1,50 @@
<template>
<v-app id="inspire">
<v-navigation-drawer v-model="drawer" fixed class="hidden-md-and-up">
<v-list dense>
<v-list-tile :to="{ name: 'dashboard'}" exact router>
<v-list-tile-content>
<v-list-tile-title>Dashboard</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-navigation-drawer>
<v-toolbar fixed app dark class="elevation-0">
<v-toolbar-side-icon @click.stop="drawer = !drawer" class="hidden-md-and-up"></v-toolbar-side-icon>
<v-toolbar-title>skillBox</v-toolbar-title>
<v-spacer></v-spacer>
<v-toolbar-items class="hidden-sm-and-down">
<v-btn flat :to="{ name: 'dashboard'}" exact router>Dashboard</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-content fluid fill-height>
<v-slide-x-transition mode="out-in">
<router-view></router-view>
</v-slide-x-transition>
</v-content>
</v-app>
</template>
<script>
export default {
name: 'App',
data() {
return {
active: null,
drawer: null,
userid: 1,
name: 'Max Muster',
email: 'skillbox@iterativ.ch'
}
},
mounted() {
}
}
</script>
<style lang="scss">
@import "styles/main";
</style>

View File

@ -0,0 +1,20 @@
import {InMemoryCache} from 'apollo-cache-inmemory/lib/index'
import {HttpLink} from 'apollo-link-http/lib/index'
import {ApolloClient} from 'apollo-client/index'
import fetch from 'unfetch'
const httpLink = new HttpLink({
uri: process.env.NODE_ENV !== 'production' ? 'http://localhost:8000/api/graphql/' : '/api/graphql/',
credentials: 'include',
fetch: fetch,
headers: {
'X-CSRFToken': document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*=\s*([^;]*).*$)|^.*$/, '$1')
}
})
// Create the apollo client
export default new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
connectToDevTools: true
})

View File

@ -0,0 +1,9 @@
query MasterBlasterQuery {
xAllUsers: allUsers {
edges {
node {
id
}
}
}
}

35
client/src/main.js Normal file
View File

@ -0,0 +1,35 @@
import 'babel-polyfill'
import Vue from 'vue'
import 'vuetify/dist/vuetify.min.css'
import Vuetify from 'vuetify'
import axios from 'axios'
import VueAxios from 'vue-axios'
import lodash from 'lodash'
import VueVimeoPlayer from 'vue-vimeo-player'
import apolloClient from './graphql/client'
import VueApollo from 'vue-apollo'
import App from './App'
import router from './router'
import store from '@/store/index'
Vue.config.productionTip = false
Object.defineProperty(Vue.prototype, '$lodash', { value: lodash })
Vue.use(VueApollo)
Vue.use(VueAxios, axios)
Vue.use(Vuetify)
Vue.use(VueVimeoPlayer)
const apolloProvider = new VueApollo({
defaultClient: apolloClient
})
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
provide: apolloProvider.provide(),
render: h => h(App)
})

View File

@ -0,0 +1,5 @@
<template>
<div>
<p>Dashboard</p>
</div>
</template>

View File

@ -0,0 +1,5 @@
<template>
<div>
<p>404 - Not Found</p>
</div>
</template>

View File

@ -0,0 +1,22 @@
import Vue from 'vue'
import Router from 'vue-router'
import Dashboard from '@/pages/PageDashboard'
import NotFound from '@/pages/PageNotFound'
const routerOptions = [
{ path: '/', name: 'dashboard', component: Dashboard },
{ path: '/dashboard', name: 'dashboard', component: Dashboard },
{ path: '*', component: NotFound }
]
const routes = routerOptions.map(route => {
return {
...route
}
})
Vue.use(Router)
export default new Router({
routes,
mode: 'history'
})

20
client/src/store/index.js Normal file
View File

@ -0,0 +1,20 @@
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
},
state: {
userid: null,
username: null
},
getters: {},
actions: {},
mutations: {}
})

View File

@ -0,0 +1,14 @@
@import "var";
body {
font-family: $font-family;
font-size: $base-font-size;
}
ul {
margin-left: 16px;
}
a {
text-decoration: none;
}

View File

@ -0,0 +1,19 @@
$grey-1: #F7F7F7;
$grey-3: #F3F3F3;
$grey-2: #D8D8D8;
$grey-4: #AFB1B1;
$grey-9: #3F3F3F;
$orange: #FD6E22;
$orange-shadow: #c54602;
$blue: #EDF7FA;
$blue-shadow: #B6CCD4;
$beige: #F3F0EB;
$text-color: $grey-9;
$font-family: 'Montserrat', Arial, sans-serif;
$base-font-size: 15px;
$learn-unit-bg-color: $beige;

5
client/src/util/uuid.js Normal file
View File

@ -0,0 +1,5 @@
export default () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = Math.random() * 16 | 0
let v = c === 'x' ? r : (r & 0x3 | 0x8)
return v.toString(16)
})

0
client/static/.gitkeep Normal file
View File

49
package-lock.json generated Normal file
View File

@ -0,0 +1,49 @@
{
"name": "cariot",
"version": "1.0.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"requires": {
"babel-runtime": "^6.26.0",
"core-js": "^2.5.0",
"regenerator-runtime": "^0.10.5"
}
},
"babel-runtime": {
"version": "6.26.0",
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
}
}
},
"core-js": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz",
"integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw=="
},
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
},
"unfetch": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-3.0.0.tgz",
"integrity": "sha1-jR4FE6Ts0OX/LUGmund3Gq6LZII="
}
}
}

15
package.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "cariot",
"version": "1.0.1",
"description": "\"Heroku client build\"",
"scripts": {
"postinstall": "npm install --prefix client && npm run build --prefix client"
},
"engines": {
"node": "8.x"
},
"dependencies": {
"babel-polyfill": "^6.26.0",
"unfetch": "^3.0.0"
}
}

15
release-tasks.sh Executable file
View File

@ -0,0 +1,15 @@
# Heroku Release Phase Script
# https://devcenter.heroku.com/articles/release-phase
# https://devcenter.heroku.com/articles/pipelines#can-i-run-scripts-such-as-rake-db-migrate-when-promoting
# Run migration
python server/manage.py migrate --no-input
# create dummy data
python server/manage.py dummy_data
# clear cache
python server/manage.py clear_cache
# Run production checks
python server/manage.py check --deploy

7
server/.env.example Normal file
View File

@ -0,0 +1,7 @@
SECRET_KEY=FOOBAR
DATABASE_URL=skillbox://skillbox:skillbox@localhost:5432/skillbox
DEBUG=True
USE_AWS=False
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_STORAGE_BUCKET_NAME=

0
server/__init__.py Normal file
View File

0
server/api/__init__.py Normal file
View File

5
server/api/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ApiConfig(AppConfig):
name = 'api'

20
server/api/schema.py Normal file
View File

@ -0,0 +1,20 @@
import graphene
from django.conf import settings
from graphene_django.debug import DjangoDebug
class Query(graphene.ObjectType):
# This class will inherit from multiple Queries
if settings.DEBUG:
debug = graphene.Field(DjangoDebug, name='__debug')
class Mutation(graphene.ObjectType):
# This class will inherit from multiple Queries
if settings.DEBUG:
debug = graphene.Field(DjangoDebug, name='__debug')
schema = graphene.Schema(query=Query, mutation=Mutation)

12
server/api/urls.py Normal file
View File

@ -0,0 +1,12 @@
from django.conf import settings
from django.conf.urls import url
from django.views.decorators.csrf import csrf_exempt
from graphene_django.views import GraphQLView
app_name = 'api'
urlpatterns = [
url(r'^graphql', csrf_exempt(GraphQLView.as_view())),
]
if settings.DEBUG:
urlpatterns += [url(r'^graphiql', csrf_exempt(GraphQLView.as_view(graphiql=True, pretty=True)))]

0
server/core/__init__.py Normal file
View File

View File

@ -0,0 +1,10 @@
from django.conf import settings
def settings_context(request):
context = {
'RAVEN_DSN_JS': settings.RAVEN_DSN_JS,
'GOOGLE_TAG_MANAGER_CONTAINER_ID': settings.GOOGLE_TAG_MANAGER_CONTAINER_ID,
'DEBUG': settings.DEBUG
}
return context

45
server/core/env_utils.py Normal file
View File

@ -0,0 +1,45 @@
import re
regex = re.compile('^<(?P<name>.*)>\s*(?P<email>.*@.*)')
def parse_emails(emails):
"""
Parse a list of emails of the following format:
<John Doe> john@abc.com, <Betty Boo> boo@bbs.com
:param str emails: "Comma separated emails"
:return: A list of name, email tuples
:rtype: list
"""
if not emails:
return []
email_tuples = []
for email in emails.split(','):
r = regex.match(email.strip())
if r:
email_tuples.append(r.groups())
return email_tuples
def bool_value(value, default=False):
"""
Convert strings like 'yes', 'y', 'true', '1',
'no', 'n', 'false', '0' or '' to boolean values.
:param str value: "Value to parse to bool"
:param bool default: "Default value if unable to convert"
:rtype: bool
"""
if not value:
return default
true_values = ('yes', 'y', 'true', '1')
false_values = ('no', 'n', 'false', '0', '')
normalized_value = value.strip().lower()
if normalized_value in true_values:
return True
elif normalized_value in false_values:
return False
else:
return default

56
server/core/factories.py Normal file
View File

@ -0,0 +1,56 @@
import random
import os
import wagtail_factories
import factory
from django.conf import settings
from django.contrib.auth import get_user_model
from factory.django import ImageField, FileField
from faker import Faker
from wagtail.documents.models import get_document_model
from wagtail.images import get_image_model
fake = Faker('de_DE')
def fake_title(x):
return fake.sentence(nb_words=random.randint(2, 4)).replace('.', '')
class BasePageFactory(wagtail_factories.PageFactory):
title = factory.LazyAttribute(fake_title)
class DummyDocumentFactory(factory.DjangoModelFactory):
class Meta:
model = get_document_model()
title = factory.LazyAttribute(fake_title)
file = FileField(
from_path=os.path.join(settings.BASE_DIR, 'core', 'static', 'doc', 'dummy.pdf')
)
class DummyImageFactory(factory.DjangoModelFactory):
class Meta:
model = get_image_model()
title = factory.LazyAttribute(fake_title)
file = ImageField(
from_path=os.path.join(settings.BASE_DIR, 'core', 'static', 'img', 'dummy.jpg')
)
class UserFactory(factory.django.DjangoModelFactory):
class Meta:
model = get_user_model()
django_get_or_create = ('username', )
first_name = factory.LazyAttribute(lambda x: fake.first_name())
last_name = factory.LazyAttribute(lambda x: fake.last_name())
email = factory.LazyAttribute(lambda x: fake.ascii_safe_email())
@factory.post_generation
def post(self, create, extracted, **kwargs):
self.set_password('test')
self.save()

View File

View File

@ -0,0 +1,29 @@
import os
import shutil
from django.conf import settings
from django.core import management
from django.core.management import BaseCommand
from django.db import connection
class Command(BaseCommand):
def ensure_clean_dir(self, folder):
path = os.path.join(settings.MEDIA_ROOT, folder)
if os.path.exists(path):
shutil.rmtree(path)
if not os.path.exists(path):
os.makedirs(path)
def handle(self, *args, **options):
with connection.cursor() as cursor:
cursor.execute("DROP SCHEMA IF EXISTS public CASCADE;")
cursor.execute(
"CREATE SCHEMA IF NOT EXISTS public AUTHORIZATION {};".format(settings.DATABASES['default']['USER']))
cursor.execute("GRANT ALL ON SCHEMA public TO postgres;")
management.call_command('migrate', verbosity=0, interactive=False)
self.ensure_clean_dir('images')
self.ensure_clean_dir('original_images')
self.ensure_clean_dir('documents')

View File

@ -0,0 +1,48 @@
import os
import shutil
import wagtail_factories
from django.conf import settings
from django.core import management
from django.core.management import BaseCommand
from django.db import connection
from wagtail.core.models import Page
from core.factories import UserFactory
data = [
]
class Command(BaseCommand):
def ensure_clean_dir(self, folder):
path = os.path.join(settings.MEDIA_ROOT, folder)
if os.path.exists(path):
shutil.rmtree(path)
if not os.path.exists(path):
os.makedirs(path)
def handle(self, *args, **options):
with connection.cursor() as cursor:
cursor.execute("DROP SCHEMA IF EXISTS public CASCADE;")
cursor.execute(
"CREATE SCHEMA IF NOT EXISTS public AUTHORIZATION {};".format(settings.DATABASES['default']['USER']))
cursor.execute("GRANT ALL ON SCHEMA public TO postgres;")
management.call_command('migrate', verbosity=0, interactive=False)
self.ensure_clean_dir('images')
self.ensure_clean_dir('original_images')
self.ensure_clean_dir('documents')
site = wagtail_factories.SiteFactory.create(is_default_site=True)
Page.objects.filter(title='Root').delete()
u = UserFactory(
username='test',
is_staff=True,
is_superuser=True
)
for i in range(0, 4):
UserFactory(username='user{}'.format(i))

76
server/core/middleware.py Normal file
View File

@ -0,0 +1,76 @@
from django.conf import settings
from django.http import Http404, HttpResponsePermanentRedirect, HttpResponseRedirect
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect
import re
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
_thread_locals = local()
def get_current_request():
""" returns the request object for this thread """
return getattr(_thread_locals, "request", None)
def get_current_user():
""" returns the current user, if exist, otherwise returns None """
request = get_current_request()
if request:
return getattr(request, "user", None)
class ThreadLocalMiddleware(MiddlewareMixin):
""" Simple middleware that adds the request object in thread local storage."""
def process_request(self, request):
_thread_locals.request = request
def process_response(self, request, response):
if hasattr(_thread_locals, 'request'):
del _thread_locals.request
return response
class CommonRedirectMiddleware(MiddlewareMixin):
"""
redirects common bad requests or missing images
"""
DEFAULT_REDIRECTS = [
(re.compile("(?i)(.+\.php|.+wp-admin.+|.+\.htm|\/wordpress\/|\/wp\/|\/mm5\/|\/wp-content\/)"),
'http://example.org/'),
]
def process_exception(self, request, exception):
if exception.__class__ == Http404:
new_path = self.not_found(request)
if new_path:
return redirect(new_path, permanent=True)
def process_response(self, request, response):
if response.status_code == 404:
new_path = self.not_found(request)
if new_path:
return HttpResponsePermanentRedirect(new_path)
return response
def not_found(self, request):
path = request.get_full_path().lower()
# generic stuff
for re_pattern, to in self.DEFAULT_REDIRECTS:
if re_pattern.match(path):
return to
if settings.USE_404_FALLBACK_IMAGE:
# some static image is missing show a placeholder (use full for local dev)
m = re.match(r".*(max|fill)-(?P<dimensions>\d+x\d+)\.(jpg|png|svg)", path)
if m:
return 'https://picsum.photos/{}'.format(m.group('dimensions').replace('x', '/'))
# or dummy image: return 'http://via.placeholder.com/{}'.format(m.group('dimensions'))
if '.png' in path or '.jpg' in path or '.svg' in path or 'not-found' in path:
return 'https://picsum.photos/400/400'

333
server/core/settings.py Normal file
View File

@ -0,0 +1,333 @@
"""
Django settings for cariot_backend project.
Generated by 'django-admin startproject' using Django 1.11.7.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import os
import sys
import dj_database_url
from django.utils.translation import ugettext_lazy as _
from dotenv import load_dotenv, find_dotenv
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
from core.env_utils import bool_value
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
load_dotenv(find_dotenv())
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = os.environ.get('SECRET_KEY')
SIGNING_SECRET = os.environ.get('SIGNING_SECRET')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = bool_value(os.environ.get('DEBUG', ''))
TEST = 'test' in sys.argv
ALLOWED_HOSTS = ['*']
if not DEBUG:
SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Application definition
INSTALLED_APPS = [
'core',
'api',
'user',
'wagtail.contrib.forms',
'wagtail.contrib.redirects',
'wagtail.embeds',
'wagtail.sites',
'wagtail.users',
'wagtail.snippets',
'wagtail.documents',
'wagtail.images',
'wagtail.search',
'wagtail.admin',
'wagtail.core',
'wagtail.api.v2',
'taggit',
'modelcluster',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'raven.contrib.django.raven_compat',
'whitenoise.runserver_nostatic',
'django.contrib.staticfiles',
'django_filters',
'graphene_django',
'django_extensions',
'compressor',
]
if DEBUG:
INSTALLED_APPS += ['wagtail.contrib.styleguide']
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware'
]
# Enable CORS for local development
if DEBUG:
INSTALLED_APPS += ['corsheaders']
MIDDLEWARE += ['corsheaders.middleware.CorsMiddleware']
CORS_ORIGIN_WHITELIST = (
'localhost:8080',
)
CORS_ALLOW_CREDENTIALS = True
MIDDLEWARE += [
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'wagtail.core.middleware.SiteMiddleware',
'wagtail.contrib.redirects.middleware.RedirectMiddleware',
'core.middleware.ThreadLocalMiddleware',
'core.middleware.CommonRedirectMiddleware',
]
ROOT_URLCONF = 'core.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, '..', 'client/dist'), os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'core.context_processors.settings_context',
],
},
},
]
WSGI_APPLICATION = 'core.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases
# Database
DATABASES = {
'default': dj_database_url.config()
}
# Django custom user
AUTH_USER_MODEL = 'user.User'
# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
WEAK_PASSWORDS = DEBUG
if WEAK_PASSWORDS:
AUTH_PASSWORD_VALIDATORS = []
else:
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = '/'
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE = 'en'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = [
('de', _('German')),
('en', _('English')),
]
LOCALE_PATHS = [
os.path.join(BASE_DIR, 'locale')
]
# Honor the 'X-Forwarded-Proto' header for request.is_secure()
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, '..', 'client/dist/static'),
)
if not TEST:
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
COMPRESS_CSS_FILTERS = [
# 'django_compressor_autoprefixer.AutoprefixerFilter',
'compressor.filters.cssmin.CSSMinFilter',
]
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'compressor.finders.CompressorFinder',
)
COMPRESS_PRECOMPILERS = (
('text/x-scss', 'django_libsass.SassCompiler'),
)
COMPRESS_ENABLED = True
if not DEBUG:
COMPRESS_STORAGE = 'compressor.storage.GzipCompressorFileStorage'
COMPRESS_OFFLINE = True
# AWS S3
# http://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html
AWS_QUERYSTRING_AUTH = False
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_FILE_OVERWRITE = False
# use with cloudfront
# AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
if bool_value(os.environ.get('USE_AWS')):
DEFAULT_FILE_STORAGE = "storages.backends.s3boto3.S3Boto3Storage"
# use with cloudfront
# MEDIA_URL = "https://%s/" % AWS_S3_CUSTOM_DOMAIN
else:
MEDIA_URL = '/media/'
MEDIA_ROOT = os.environ.get('DJANGO_MEDIAFILES', os.path.join(BASE_DIR, 'media'))
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
# Media Files
USE_404_FALLBACK_IMAGE = bool_value(os.environ.get('USE_404_FALLBACK_IMAGE', 'True'))
# Logging Conf
LOGGING = {
'version': 1,
'formatters': {
'verbose_format': {
'format': '%(levelname)s %(asctime)s %(module)s %(name)s (%(process)d): %(message)s'
},
'simple_format': {
'format': '%(levelname)s %(name)s: %(message)s'
},
},
'disable_existing_loggers': True,
'handlers': {
'mail_admins': {
'level': 'CRITICAL',
'class': 'django.utils.log.AdminEmailHandler'
},
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'simple_format'
},
},
'loggers': {
'': {
'handlers': ['console'],
'level': 'INFO',
'propagate': True,
},
'django.security.DisallowedHost': {
'handlers': ['mail_admins'],
'level': 'CRITICAL',
'propagate': False,
},
}
}
if not DEBUG and os.environ.get('RAVEN_DSN'):
# import raven
RAVEN_CONFIG = {
'dsn': os.environ.get('RAVEN_DSN'),
}
LOGGING['handlers'] = {
'sentry': {
'level': 'ERROR', # ERROR, WARNING, INFO
'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
'tags': {'custom-tag': 'x'},
},
'console': {
'level': 'INFO',
'class': 'logging.StreamHandler',
'stream': sys.stdout,
'formatter': 'simple_format'
}
}
for k, v in LOGGING['loggers'].items():
LOGGING['loggers'][k]['handlers'] = ['sentry', 'console']
else:
RAVEN_CONFIG = {}
RAVEN_DSN_JS = os.environ.get('RAVEN_DSN_JS', '')
GOOGLE_TAG_MANAGER_CONTAINER_ID = os.environ.get('GOOGLE_TAG_MANAGER_CONTAINER_ID')
GRAPHENE = {
'SCHEMA': 'api.schema.schema'
}
if DEBUG:
GRAPHENE['MIDDLEWARE'] = [
'graphene_django.debug.DjangoDebugMiddleware',
]
# http://docs.wagtail.io/en/v2.1/advanced_topics/settings.html?highlight=urls
WAGTAIL_SITE_NAME = 'skillBox'

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -0,0 +1,97 @@
@import "materialize/materialize";
$white: #fff;
$grey-1: #F7F7F7;
$grey-3: #F3F3F3;
$grey-2: #D8D8D8;
$grey-4: #AFB1B1;
$grey-9: #3F3F3F;
$light-white: rgba(255, 255, 255, 0.12);
$orange: #FD6E22;
$orange-shadow: #c54602;
$red: #cd3238;
$red-shadow: darken($red, 20%);
$blue: #EDF7FA;
$blue-shadow: #B6CCD4;
$text-color: $grey-9;
$font-family: 'Arimo', Arial, sans-serif;
$base-font-size: 15px;
$space: 10px;
body {
font-family: $font-family;
font-size: $base-font-size;
color: $text-color;
}
h4, .h4 {
font-size: 18px;
}
a {
text-decoration: none;
}
.alert {
padding: $space;
}
.alert-error {
border: 1px solid $red-shadow;
background-color: #cd3238;
}
.alert-info {
border: 1px solid $blue-shadow;
background-color: $blue;
color: $text-color;
}
.orange-bg {
background-color: $orange;
}
.dark-bg {
background-color: $grey-9;
color: $white;
}
.btn-orange {
border: 1px solid $orange !important;
background-color: transparent;
border-radius: 2px;
color: $white;
&:hover, &:focus {
background-color: $orange-shadow;
}
box-shadow: none;
}
input[type=text], input[type=password], select {
width: 100%;
padding: $space;
margin: 8px 0;
display: inline-block;
border: 1px solid $grey-4;
border-radius: 2px;
box-sizing: border-box;
background-color: $light-white;
color: $white;
}
.mt-1 {
margin-top: $space;
}
.mb-1 {
margin-bottom: $space;
}

View 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;
}

View File

@ -0,0 +1,321 @@
// 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 {
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;
}

View 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;
}
}
}

View 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;
}
}

View 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%);
}

View File

@ -0,0 +1,84 @@
.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 {
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;
}
}
.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);
}
}

View 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;
}
}

View 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;
}

View File

@ -0,0 +1,187 @@
/* 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-controls,
.datepicker-table,
.datepicker-footer {
width: 320px;
}
.datepicker-day-button {
line-height: 44px;
}
}

View File

@ -0,0 +1,76 @@
.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: 0;
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;
background-color: darken($dropdown-hover-bg-color, 8%);
}
&.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;
}
}
// Input field specificity bugfix
.input-field.col .dropdown-content [type="checkbox"] + label {
top: 1px;
left: 0;
height: 18px;
transform: none;
}

View 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;
}

View 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;
}
}
}
}

View File

@ -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';
}

View 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;
}

View File

@ -0,0 +1,90 @@
.modal {
@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;
}

View 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;
}
}

View 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;
}

View 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; }
}

View 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);
}
}

View File

@ -0,0 +1,216 @@
.sidenav {
position: fixed;
width: 300px;
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;
}

View 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;
}
}
}
}

View 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;
}
}
}

View 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;
}
}
}
}

View 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;
}
}

View 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;
}
}

View File

@ -0,0 +1,59 @@
#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;
word-break: break-all;
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;
}
}

View 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;
}

View 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;
}

View 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;
}
}

View File

@ -0,0 +1,348 @@
// ==========================================================================
// 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("materialize-red", "lighten-2") !default;
$primary-color-light: lighten($primary-color, 15%) !default;
$primary-color-dark: darken($primary-color, 15%) !default;
$secondary-color: color("teal", "lighten-1") !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-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;

View 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;
}

View 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;
}
}

View 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);
}
}

View 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';

View File

@ -0,0 +1,352 @@
/* 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;
}
}
& > 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;
}

View 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;
}

View 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;
}
input[type=range].focused: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;
}
input[type=range].focused: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;
}
input[type=range].focused:focus:not(.active)::-ms-thumb {
box-shadow: 0 0 0 10px rgba($radio-fill-color, .26);
}

View File

@ -0,0 +1,178 @@
/* 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;
}
.select-dropdown.dropdown-content {
li {
&:hover {
background-color: $select-option-hover;
}
&.selected {
background-color: $select-option-selected;
}
&:focus {
background-color: $select-option-focus;
}
}
}
// 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;
}
}

View 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;
}

View File

@ -0,0 +1,38 @@
@charset "UTF-8";
// Color
@import "components/color-variables";
@import "components/color-classes";
// Variables;
@import "components/variables";
// Reset
@import "components/normalize";
// components
@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";

Some files were not shown because too many files have changed in this diff Show More