diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2302cde
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# ElixirCode
+
+
+
+Each example from the course can be found within this repo. You can either look at the files in a completed state, or check out the changes that were made in each video by using the branch browser.
diff --git a/diagrams.xml b/diagrams.xml
new file mode 100644
index 0000000..3bd5cb9
--- /dev/null
+++ b/diagrams.xml
@@ -0,0 +1 @@
+7ZhNj5swEIZ/Sw9cK7CTlBwbdtteWlXKYc8OTMBag5FjStJf33EYCBRWm42UnCBSZL/jD/w+Y748HuXH70aU2U+dgPKYnxw9/uQx9mW1wH8nnBqBL9eNkBqZNFJwEbbyL5Dok1rJBA6DhlZrZWU5FGNdFBDbgSaM0fWw2V6r4aylSGEkbGOhxuqLTGxGauD7l8APkGlGU4dLCuxE/JoaXRU0n8f4/nw04Vy0Y1H7QyYSXfck/uzxyGhtm1J+jEA5a1vbmn7f3oh2522gsNd0YE2HP0JVtPQnadBRbU7u7KypYlsZwHJVJsICnbU9tU6d1wpuNN/jmzqTFraliF20xtRALbO5wlqAxW61rq0SO1Cbzq9IK20wVOgCXFNr9Cu0Itroh+7XRVos6NhmL5XqtSTDUdeFpdxijOr9Ec8H6kLJtEAtRtMAgxsyBYyF45vGBh0u3AWgc7Bnz6gDbwnTDmALqteXfGJr0rJeKq1IE5TCaTf0BSMWiOQ01cWI6gvsaB/gAhFgqaR1HQq3s2o9Y70WazjEyv0HYl2OsEZKuhN3wx7AHhxDwMXgRk1mpLciXT0Q6WqE9BfUKEQ6zwXeRJi/zbSxcWUPn2aiN157g/CBRMMR0WAGdyU4Fr4PbnEnbusRNzZzu5Hb1MPOvbi1rwx9cGImd+2lcvH+88zdyAVjcruZ3K3kJh5b7kZu/Nr4O9NQyKMTg898RBHXaf9DNfCfoPSNJmnknXNN4qv6VwrkMkncNJO5McyeD6THtWjvcdebuHoGfAIl+zhKrF4+LpxjvQ84/Pkf 7ZvPb9sgFMf/mlwrG+z8ODZZux02aVIP204TtalNi02ESZPsr98jxokd3CpxUnYYqVSFL2Cb93kYeK8d4UWx+SzJMv8mUspHKEg3I/xphNAsnMBvLWxrIcJBLWSSpbUUHoQH9ocasWm2YimtOg2VEFyxZVdMRFnSRHU0IqVYd5s9Cd6965Jk1BIeEsJt9QdLVW7UMAgOFV8oy3Jz62lsKh5J8pJJsSrN/UYIP+0+dXVBmmuZ9lVOUrFuSfhuhBdSCFV/KzYLyrVpG7PV/e7fqN0/t6SlOqUDqju8Er4yQ1/TR/NoatuYYzcgqrsEIzxf50zRhyVJdO0a+IOWq4JDKYSv+yHptpw8Uj7fG2UhuJBQVYqS6qZKihfaiGCrYKp/9jWN7cEs8yfGeaulsSroolTGgRAy5fYVdx/QCWdZCVoClqFQOTcjp1LRzZvWC/dMwNWpKKiSW2hiOqCpwWjcPJyY8rrlNI1r5C1/QVPjq8ZPs/2lD6zgi8HVjw5b6L7ngpZsA2J4gyyIMEx1RKpjfsOkbWcjWabTRmMwW25NRcHSVN+m1zW6znOGd7TI4vfIXgPk+Agkim2Qsx6QzXvtEpCRhYqm8DYyRSFVLjJREn53UI+M2mJKN0z91PJNbEq/TCMwhdy2qnSxqasUkepWvzjbkxO0e6Yf2/RPmxYJJ1XFklo0TfTNn6lSW4OMrJQA6fD4X4VY9jpem2V33uOzvUBb7n0fAEOLlUxoZxLBUDOqWpLtKZJyothr9+qXYI/fnb/Yz98z5u84/Ifzd2KBTHIC+xJe+YX0RH44OOI3m7pbSKc2Pxi6FJxT6REORQiT0h3CmYWw0EcST28wvThyR695ebfwweYDViiPbyi+KXKIL7TwwfaQKj/7TsaHuvhw6PAcGY7t9a/y7Aazww63LqG993z26AajG/ecGj4Mnb3tVLRYwiGTeoJD1z08ww4J2rvOV0bXnt5QelFzCRf0kL3pBBvD2G5gPJ7gQILRzCFBO3nBmU9enBwza7r8i+RFT/YiZVWy8hvP0/lF4y4/lzGzJmlh8/vtE4jDGTo9t/dkIEiSgJX/l5P7rqMZI7oGzfERTZchUGQf45ei8iivhNJlPNRnlK4P0GlIzaeUPoahy9BaT07Jx2cuJjh2uCJi+4Tv4zMX0Zs5XASxnVXy8ZlLCUZNzMQJQTs+4/OCF4VootjhJgbbIRqfWzrjZB910MWBy5XPjs74lO5wdtHk4/adUDz8tf+urvUfFfjuLw== 7Zldk5owFIZ/DbcOSfzay+putzed6YwXvc7CEdINiRNj1f76nkBAEHR3XbUXRUcH3hyCOc/JS8CAzbPds+Gr9LuOQQY0jHcBewwofSAT/HbCvhCGLCyExIi4kMhBWIg/4MUybCNiWDcCrdbSilVTjLRSENmGxo3R22bYUsvmWVc8gZawiLhsqz9FbFOvkjA8NHwDkaT+1NORb3jh0Wti9Eb58wWULfNX0Zzxsi8fv055rLc1iT0FbG60tsVWtpuDdKkt01Yc9/VEa/W7DSj7ngNoccBvLjd+6JnYuR5SDUrsBgq2/ofafZmcfHjgOggDNtumwsJixSPXusVqQC21mcQ9gpvVAF2s5C8gZ1WK5lpqg01KK3Ch1uhXKEXMXDh176qlJIFJmi2FlLVIn2PUtbK+nCj1+/Ue8xfqXIpEoRZhngAbZz4PYCzsTuaSVISw8EFnYM0eQ/wBrKwOX/Rk7Pe3hxJiJfi0Vj1lHPdVm1RdH8jhhofXDXJ4EmQP8SMQx/QfQhy3ID6DAsMtuDEY/ct53TFJHKs9wtVg4MHUk+2lVv5c5gS64BffkIk4dqfprI9mBX2gRN6L9wo0CTmiOW3TJJNRmya9As3JG966BoOD62fmhfZaMbrHzJyesdee46cc9q4cH1ocF5YbNNVw0U2xd9cz7joaNUkOO9yVdZC8hruWzn7SXjE5Fu8h+ml5ob12XCpvNi0JOeOvPcjP+etdQY7aBpti4rHXPO4Ey95lz7gsa/KsJmrdZUc3WsOStxaxCahBlHKl3AOgfoZeZLWs47p5uxl6binb0/y8396XZntBW3tkwPGTP/wJK6ghphB6//2I/1LW5NvxRIhMbrTKpe1V7o/CeVEkA/r/kMzj/DjJFbCyaRMr6bgNvdlllbbXu3WsrMd6KdZJeD+suHv4pyZvq/0bxp7+Ag== 7VfJbtswEP0aXQIkkCXLdo6x47QFugE+tDkVtDSW2NCkStFbvr5DabRFtqE06AI0DmKLb4YUOe89kXL82Xr/RrM0+aAiEI7nRnvHv3U873owxm8LHApg6LsFEGseFdCgBhb8EQgs0zY8gqyVaJQShqdtMFRSQmhaGNNa7dppKyXad01ZDB1gETLRRb/wyCSEDly3DrwFHid060lAgSULH2KtNpLu53j+Kv8U4TUrx6L8LGGR2jUgf+74M62UKa7W+xkIW9qybEW/uxPRat4apOnTwSs6bJnY0NIjnoWbLPu2gyVN0RzKsuQLA9vVdfzpLuEGFikLbXSHOkAsMWuBrQFeVkuzuYItQUyr4syUUBpDUkmwqUarByhBrJk7sX9VpOQAyzNdcSEamVRdxJU0JCTPo3ZzxPyDOBM8loiFWCHA4JQqANrA/mQVBxU3KHlQazD6gCnUwbsmOku5T6i9a4hnTFjS0M1oQpolvcbV0DVneEG0HafQP0XhK3096RsN/iJ9QYcmiPBZRE2lTaJiJZmY1+i0TWSDNNhz89XCVzhu0bwv+TRMmxv7bGwSh9gdt3PLRwIZlRmhYFnGwwKkFDvMdzDmQESxjVEI1XN8r1Ra3e6pJkoG25rwn8F9USlbnvNEYzXVRoeUNaT9g+kYTOOp15WDBsEM37ZHfwm344417+eLDt8oXNOmUUPGH9kyT7ALTxWXJp9HMHWC22M2sAbguIHdUGDNoyjXygnr/or3TlqNtmGacb27NZkJzlrw0r1yveGwZcNLGr03LTT6Z1utRoparTJk/ilv1SR6UTn6PTYdv9r0tE39P2TTScemHz/9py4dnXUpmnQ4uP6HXDnsMHer8L0BZZRAvuLI/rzDfwloRPsWYbd1jScfu5Wzrf25YPJgEi7jizIhyrM4Kt+uMwS+xSheY60tkKVKRgWSp7Mc/bGBDKt410M5bdeRy5snI4L66+fYYa79+HnGee7FSut/9PKD9tHLC7pHL3905OhVnrif4Xts1i9Whdjql1d//hM= 7ZhNc9owEIZ/DdeMLWNwjglN2kM705kcmp46wl5sNbLEyHKA/vpK8tpY2GGSUJoLMMNI766+9pFW2JNoUW4/K7ouvskM+IQE2XYSfZoQMp9Nza8Vdo0QxdeNkCuWNVK4Fx7YH0AxQLVmGVSeo5aSa7b2xVQKAan2NKqU3PhuK8n9Udc0h4HwkFI+VH+wTBeohkGwN3wBlhc4dBKjYUnTp1zJWuB4ExKt3Kcxl7TtC/2rgmZy05Oiu0m0UFLqplRuF8BtaNuwNe3uX7B281Yg9GsazHEaetcuHTITCaxKpQuZS0H53V69dcsD20FgaoUuuSmGpghbph975Z/W5YrEtiq02j1iE1dpjNZWaar0jaVmJCEFtNo947xrkrUeKadVxdJGRBc74m/QeodbidZaGmk//69SrtGv0ko+wUJyqdyKo8B9OksLPDLKSgqNXUYE62Mtmyja0L3IAaVK1ipFL4I7m6oc0Cvu9oA5WiBLMJEyLgo41ezZ753iJs87vz1oU0DW49yT83OfX9j6bGf/iS0O/Ux5jZ1uYDng7dPcFEzDw5q66W9MTvcJd2nK+nK6BH7bJbo2Zh3dQwSJ/Q4QuJAbwj1PzJQeGnIMDeUsF3bbGBKgOlbPoDRsj9MacsAGJMG7C68uEmI8N72LoE33Re8OmCWno4sG6L4XEgTbGjG8IgOIZpn6gJQXfmTSjzNKg9DZoDFzA96goWRZ5o792NbwN88bdsfbDt1pIOeBB/I6GHK8HuEYBadznB7lGF04voFjPP04jvGAY8aqtK6qSzp9Lb2ZTy+cTof45mdKp7OX8P263IjvR0iSkRN4LoTtE2GP4cKsnTJR2cetumIC7HEMuMzNH0czmHn0Mg+eVNMlrcAKaQojB/b0lMthpT8i4YbHNoDzw1WSfwB/fpB9w3jk71A4Ar/1Owl+eAx+KjNwLwZcuSxrYTBocHMzUzOWwlVGjvoF/rvgkyQ5G3xT3b/2cLbeq6Xo7i8= 5ZVNj5swEIZ/DcdKfGTbcNyk293LnnLoeQIDWDEYGWeT9Nd3xgwESiLtSrmVSBF+Z4yZeR+bINnW51cLbfVuctRBHObnIPkZxHEa/aB/Fi69sErCXiitynspugo79QdFHNKOKsduluiM0U61czEzTYOZm2lgrTnN0wqj56u2UOJC2GWgl+pvlbtK1CgMr4E3VGUlS6+fJLCH7FBac2xkvSBOCn/14RqGZ0l+V0FuThMpeQmSrTXG9Xf1eYuaWzu0rZ/36050fG+LjfvMhLif8AH6KKVvTePw7OT13GVoiS8KeVoYJJtTpRzuWsg4eiIGSKtcrWkU0e1YFudq2KPejI3ZGm0shRrTIKc6aw44iNSvcM2/MTL0n1qzKZTWk0zpLOn0zgJRHMt4+kR/kQ5alQ1pGXUHKbiR6tFSyXc7GI2+EO5oanT2QikyYTUwIahHqYxPV3DitWjVhJnvooGwWo6PvvpFN2LZHb+jm/6Bajp+ss91FfqdkqMfgON9iV1m1R45qyKjKLcv2qnsqMGy9ZfOYc1rNfRnjqxB23Jhxh66BR8emjkEM2fF7qmFIi1cYT8UbcZnCdQqz3mZm9TNufwCeJ+F5gGMJOnTjJHR+ykj6Q1G0kcwstzjrwY4wxT9EcrW0QLPfPCqD/yHnBwcfLOowVGXSYSO3V9iASwgdBcfJCcL9okPbmHG10vl/jfk+DypM3oERqt0htF49EwwWoXxQzCi4fUr5GOTL33y8hc= 7ZZNb6MwEIZ/DXfASZMeN7S7vfSUXe3ZhQlYtT3IOEvYX7/jMBBYUimVKvVSIiH7nfHX+wxyIpGZ0w8n6+oZC9BRGhenSDxEaXqfbOgdhK4XViLuhdKpopeSi7BXf4HFIe2oCmhmiR5Re1XPxRythdzPNOkctvO0A+r5qrUsYSHsc6mX6m9V+IrVJI4vgSdQZcVLb9cceJH5a+nwaHm9KBWH89OHjRzm4vymkgW2E0k8RiJziL5vmVMGOlg72NaP+/5GdNy3A+tvGZD2A/5IfeSj/2rANbw53w2GnI8EYVAciV1bKQ/7WuYh2lIFkFZ5o6mXUHM8VMjV8gX0brQlQ42OQhYthFTv8BUGkdyKt+E3Rgb3yZjdQWk9yWRfSUfruYTSLfenM54f0qVWpSUtJ2+Agjs+OzgPpzf9S0YqVOyABrzrKIUHpPfrfkg39BlsOymbDWvVpGLuWJNcqeU49YUWNRjYdXhiAe8n1ir/oncrvbvhe/4MeqsFvQyNoZ1/8buV32bzifzWC377rvFgmpBj6fWgmvzYLGnSef1/yGYcGM7UcJYWHgb3FF1b3zhgVFGEZa7WyLyK3lEmtyL+AKKrRMyIJleI0m27JLp6P1HqXi7ac2zyZ0Y8/gM= 7VfJbtswEP0a3bV4yzF2kvZSoIBR9EyTtESEIg1qVNn9+g7F0RY5hdP6GBkQxDcLOfMeKTnKduX5i2On4psVUkdpLM5R9hSl6UOyxrsHLgFYZHEAcqdEgJIB2KvfksDOrVZCVhNHsFaDOk1Bbo2RHCYYc842U7ej1dNZTyyXM2DPmZ6jP5WAgtAkjgfDV6nygqbeLMlwYPw1d7Y2NF+UZsf2CuaSdbnIvyqYsM0Iyp6jbOeshfBUnndS+9Z2bQtxL+9Y+3U7aeCWgDQE/GK6ptK/26pSB2xEGu+sAXmGyvsbvD2pitdVRSuHS9ettl7pM8ZRtm0KBXJ/YtxbG5QHYgWUGkcJPvYVe1/NDlJv+57trLYOTcYa6V3B2VfZgdjKeON/vaWjBru2PSqtR57UdMSxBtJXmtJ4nLG9EGda5QYxjo2TaNxSY6TDFrzb3KSnDHeCtKUEd0EXCkgXxDLtgmRN42bQVNbtjGIkpxVhjGSc96kHKvGB2LzO7GLG7CPn2GT45O9W/rLllL80m/OXbq7w158T/0Pg8trW9Ozthq2orCHgxbq6/KT2X6nNbqY2uQO1qxm1z1jNBQplcsSd1AyQNP/Sw9uPSjpiWRmuaxG8WA0FVqs4A5RBsJ9YVTXWiTZJJSGgLGx8rwwJgNGUTQKfCcYf+G9UMaGa+B9zSlBHk5ZHn8HTg2vTjwSXSgg/yVURTmX6AR2ONJSs/qKh1o+qTO+gn9Xbo2GxnOsnvaKf9R3ks/6QfMCeFPfvcGZE+8lUltLAFUEV2HOKOaI0inHs0dnSjwv/XSAOIXgUwJ3EOYNHObNqy8Q4W6PAZ2dtVSHnsKwY1LB4BZ9SvbNU+6NvLNWH+0gVh8O3a2sb/T/Inv8A 7VVNc5wwDP01XDOAQ7rXhU3aS0/bTs+O0YIntsUYE9j++spgYMk2M+nH5BQutp5ky9J7NhEr9PDZ8qb+iiWoKI3LIWKHKE2T5PaOBo+cJyRjuwmorCxD0Aoc5U8IYBzQTpbQbgIdonKy2YICjQHhNhi3Fvtt2AnVNmvDK7gCjoKra/SHLF091xXHq+MLyKoOqXdZcDxy8VRZ7EzIF6XsNH6TW/N5rxDf1rzE/gJi9xErLKKbZnooQPnezm2b1j284l3ObcG4tyxg04JnrrpQupaD36EebiowN7XTPnwvBNXkWpp+b8HS0NHgTdBcqojtW2elqUJR7jw30sFA58jHbdghoSkF4hMUqNASYtBQZH6SSr2AuJKVIVNQJZSR5c9gnSSK9sGhZVn6NHlfSwfHhgufsydBEjZSAL7I2Oecu+wNxR9B5QtPL0+CxgU9prtgzyFEZjx+hIe+0ZlgeLX3ycIo3RRADc6eKSQsSJNsWhIuSTKLol8ld/cpYPWF2max8aDyatl6ZZomgezfE3/7NuIPshVd20o0nuxv2Egx3kUaPeCk8xR8sP/v7C9v33uwn/0N+wVq7Yvzz+44a6cX2I0Vf2jgzzWQMLbRAIuvNbBj2X/RAJnrb2X0Xfy72f0v
\ No newline at end of file
diff --git a/discuss/.gitignore b/discuss/.gitignore
new file mode 100644
index 0000000..19fe3da
--- /dev/null
+++ b/discuss/.gitignore
@@ -0,0 +1,24 @@
+# App artifacts
+/_build
+/db
+/deps
+/*.ez
+
+# Generated on crash by the VM
+erl_crash.dump
+
+# Static artifacts
+/node_modules
+
+# Since we are building assets from web/static,
+# we ignore priv/static. You may want to comment
+# this depending on your deployment strategy.
+/priv/static/
+
+# The config/prod.secret.exs file by default contains sensitive
+# data and you should not commit it into version control.
+#
+# Alternatively, you may comment the line below and commit the
+# secrets file as long as you replace its contents by environment
+# variables.
+/config/prod.secret.exs
diff --git a/discuss/README.md b/discuss/README.md
new file mode 100644
index 0000000..278e891
--- /dev/null
+++ b/discuss/README.md
@@ -0,0 +1,20 @@
+# Discuss
+
+To start your Phoenix app:
+
+ * Install dependencies with `mix deps.get`
+ * Create and migrate your database with `mix ecto.create && mix ecto.migrate`
+ * Install Node.js dependencies with `npm install`
+ * Start Phoenix endpoint with `mix phoenix.server`
+
+Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
+
+Ready to run in production? Please [check our deployment guides](http://www.phoenixframework.org/docs/deployment).
+
+## Learn more
+
+ * Official website: http://www.phoenixframework.org/
+ * Guides: http://phoenixframework.org/docs/overview
+ * Docs: https://hexdocs.pm/phoenix
+ * Mailing list: http://groups.google.com/group/phoenix-talk
+ * Source: https://github.com/phoenixframework/phoenix
diff --git a/discuss/brunch-config.js b/discuss/brunch-config.js
new file mode 100644
index 0000000..d2fe679
--- /dev/null
+++ b/discuss/brunch-config.js
@@ -0,0 +1,69 @@
+exports.config = {
+ // See http://brunch.io/#documentation for docs.
+ files: {
+ javascripts: {
+ joinTo: "js/app.js"
+
+ // To use a separate vendor.js bundle, specify two files path
+ // http://brunch.io/docs/config#-files-
+ // joinTo: {
+ // "js/app.js": /^(web\/static\/js)/,
+ // "js/vendor.js": /^(web\/static\/vendor)|(deps)/
+ // }
+ //
+ // To change the order of concatenation of files, explicitly mention here
+ // order: {
+ // before: [
+ // "web/static/vendor/js/jquery-2.1.1.js",
+ // "web/static/vendor/js/bootstrap.min.js"
+ // ]
+ // }
+ },
+ stylesheets: {
+ joinTo: "css/app.css",
+ order: {
+ after: ["web/static/css/app.css"] // concat app.css last
+ }
+ },
+ templates: {
+ joinTo: "js/app.js"
+ }
+ },
+
+ conventions: {
+ // This option sets where we should place non-css and non-js assets in.
+ // By default, we set this to "/web/static/assets". Files in this directory
+ // will be copied to `paths.public`, which is "priv/static" by default.
+ assets: /^(web\/static\/assets)/
+ },
+
+ // Phoenix paths configuration
+ paths: {
+ // Dependencies and current project directories to watch
+ watched: [
+ "web/static",
+ "test/static"
+ ],
+
+ // Where to compile files to
+ public: "priv/static"
+ },
+
+ // Configure your plugins
+ plugins: {
+ babel: {
+ // Do not use ES6 compiler in vendor code
+ ignore: [/web\/static\/vendor/]
+ }
+ },
+
+ modules: {
+ autoRequire: {
+ "js/app.js": ["web/static/js/app"]
+ }
+ },
+
+ npm: {
+ enabled: true
+ }
+};
diff --git a/discuss/config/config.exs b/discuss/config/config.exs
new file mode 100644
index 0000000..cb36295
--- /dev/null
+++ b/discuss/config/config.exs
@@ -0,0 +1,36 @@
+# This file is responsible for configuring your application
+# and its dependencies with the aid of the Mix.Config module.
+#
+# This configuration file is loaded before any dependency and
+# is restricted to this project.
+use Mix.Config
+
+# General application configuration
+config :discuss,
+ ecto_repos: [Discuss.Repo]
+
+# Configures the endpoint
+config :discuss, Discuss.Endpoint,
+ url: [host: "localhost"],
+ secret_key_base: "u9hBRCWHemNRWIx/RnJ6J4TY3NYqN0PXCBS22vQwmwxoKgG0oJ1UOUvZYtd1gOb6",
+ render_errors: [view: Discuss.ErrorView, accepts: ~w(html json)],
+ pubsub: [name: Discuss.PubSub,
+ adapter: Phoenix.PubSub.PG2]
+
+# Configures Elixir's Logger
+config :logger, :console,
+ format: "$time $metadata[$level] $message\n",
+ metadata: [:request_id]
+
+# Import environment specific config. This must remain at the bottom
+# of this file so it overrides the configuration defined above.
+import_config "#{Mix.env}.exs"
+
+config :ueberauth, Ueberauth,
+ providers: [
+ github: { Ueberauth.Strategy.Github, [] }
+ ]
+
+config :ueberauth, Ueberauth.Strategy.Github.OAuth,
+ client_id: "9239f35642a875b098aa",
+ client_secret: "fbfacf2758ec121ddaa3931d7bc1ba1b4441fc5d"
diff --git a/discuss/config/dev.exs b/discuss/config/dev.exs
new file mode 100644
index 0000000..906fecf
--- /dev/null
+++ b/discuss/config/dev.exs
@@ -0,0 +1,43 @@
+use Mix.Config
+
+# For development, we disable any cache and enable
+# debugging and code reloading.
+#
+# The watchers configuration can be used to run external
+# watchers to your application. For example, we use it
+# with brunch.io to recompile .js and .css sources.
+config :discuss, Discuss.Endpoint,
+ http: [port: 4000],
+ debug_errors: true,
+ code_reloader: true,
+ check_origin: false,
+ watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
+ cd: Path.expand("../", __DIR__)]]
+
+
+# Watch static and templates for browser reloading.
+config :discuss, Discuss.Endpoint,
+ live_reload: [
+ patterns: [
+ ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
+ ~r{priv/gettext/.*(po)$},
+ ~r{web/views/.*(ex)$},
+ ~r{web/templates/.*(eex)$}
+ ]
+ ]
+
+# Do not include metadata nor timestamps in development logs
+config :logger, :console, format: "[$level] $message\n"
+
+# Set a higher stacktrace during development. Avoid configuring such
+# in production as building large stacktraces may be expensive.
+config :phoenix, :stacktrace_depth, 20
+
+# Configure your database
+config :discuss, Discuss.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "stephengrider",
+ password: "",
+ database: "discuss_dev",
+ hostname: "localhost",
+ pool_size: 10
diff --git a/discuss/config/prod.exs b/discuss/config/prod.exs
new file mode 100644
index 0000000..341b365
--- /dev/null
+++ b/discuss/config/prod.exs
@@ -0,0 +1,61 @@
+use Mix.Config
+
+# For production, we configure the host to read the PORT
+# from the system environment. Therefore, you will need
+# to set PORT=80 before running your server.
+#
+# You should also configure the url host to something
+# meaningful, we use this information when generating URLs.
+#
+# Finally, we also include the path to a manifest
+# containing the digested version of static files. This
+# manifest is generated by the mix phoenix.digest task
+# which you typically run after static files are built.
+config :discuss, Discuss.Endpoint,
+ http: [port: {:system, "PORT"}],
+ url: [host: "example.com", port: 80],
+ cache_static_manifest: "priv/static/manifest.json"
+
+# Do not print debug messages in production
+config :logger, level: :info
+
+# ## SSL Support
+#
+# To get SSL working, you will need to add the `https` key
+# to the previous section and set your `:url` port to 443:
+#
+# config :discuss, Discuss.Endpoint,
+# ...
+# url: [host: "example.com", port: 443],
+# https: [port: 443,
+# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
+# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
+#
+# Where those two env variables return an absolute path to
+# the key and cert in disk or a relative path inside priv,
+# for example "priv/ssl/server.key".
+#
+# We also recommend setting `force_ssl`, ensuring no data is
+# ever sent via http, always redirecting to https:
+#
+# config :discuss, Discuss.Endpoint,
+# force_ssl: [hsts: true]
+#
+# Check `Plug.SSL` for all available options in `force_ssl`.
+
+# ## Using releases
+#
+# If you are doing OTP releases, you need to instruct Phoenix
+# to start the server for all endpoints:
+#
+# config :phoenix, :serve_endpoints, true
+#
+# Alternatively, you can configure exactly which server to
+# start per endpoint:
+#
+# config :discuss, Discuss.Endpoint, server: true
+#
+
+# Finally import the config/prod.secret.exs
+# which should be versioned separately.
+import_config "prod.secret.exs"
diff --git a/discuss/config/test.exs b/discuss/config/test.exs
new file mode 100644
index 0000000..258d032
--- /dev/null
+++ b/discuss/config/test.exs
@@ -0,0 +1,19 @@
+use Mix.Config
+
+# We don't run a server during test. If one is required,
+# you can enable the server option below.
+config :discuss, Discuss.Endpoint,
+ http: [port: 4001],
+ server: false
+
+# Print only warnings and errors during test
+config :logger, level: :warn
+
+# Configure your database
+config :discuss, Discuss.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "postgres",
+ password: "postgres",
+ database: "discuss_test",
+ hostname: "localhost",
+ pool: Ecto.Adapters.SQL.Sandbox
diff --git a/discuss/lib/discuss.ex b/discuss/lib/discuss.ex
new file mode 100644
index 0000000..0079ec4
--- /dev/null
+++ b/discuss/lib/discuss.ex
@@ -0,0 +1,31 @@
+defmodule Discuss do
+ use Application
+
+ # See http://elixir-lang.org/docs/stable/elixir/Application.html
+ # for more information on OTP Applications
+ def start(_type, _args) do
+ import Supervisor.Spec
+
+ # Define workers and child supervisors to be supervised
+ children = [
+ # Start the Ecto repository
+ supervisor(Discuss.Repo, []),
+ # Start the endpoint when the application starts
+ supervisor(Discuss.Endpoint, []),
+ # Start your own worker by calling: Discuss.Worker.start_link(arg1, arg2, arg3)
+ # worker(Discuss.Worker, [arg1, arg2, arg3]),
+ ]
+
+ # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
+ # for other strategies and supported options
+ opts = [strategy: :one_for_one, name: Discuss.Supervisor]
+ Supervisor.start_link(children, opts)
+ end
+
+ # Tell Phoenix to update the endpoint configuration
+ # whenever the application is updated.
+ def config_change(changed, _new, removed) do
+ Discuss.Endpoint.config_change(changed, removed)
+ :ok
+ end
+end
diff --git a/discuss/lib/discuss/endpoint.ex b/discuss/lib/discuss/endpoint.ex
new file mode 100644
index 0000000..525909b
--- /dev/null
+++ b/discuss/lib/discuss/endpoint.ex
@@ -0,0 +1,42 @@
+defmodule Discuss.Endpoint do
+ use Phoenix.Endpoint, otp_app: :discuss
+
+ socket "/socket", Discuss.UserSocket
+
+ # Serve at "/" the static files from "priv/static" directory.
+ #
+ # You should set gzip to true if you are running phoenix.digest
+ # when deploying your static files in production.
+ plug Plug.Static,
+ at: "/", from: :discuss, gzip: false,
+ only: ~w(css fonts images js favicon.ico robots.txt)
+
+ # Code reloading can be explicitly enabled under the
+ # :code_reloader configuration of your endpoint.
+ if code_reloading? do
+ socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
+ plug Phoenix.LiveReloader
+ plug Phoenix.CodeReloader
+ end
+
+ plug Plug.RequestId
+ plug Plug.Logger
+
+ plug Plug.Parsers,
+ parsers: [:urlencoded, :multipart, :json],
+ pass: ["*/*"],
+ json_decoder: Poison
+
+ plug Plug.MethodOverride
+ plug Plug.Head
+
+ # The session will be stored in the cookie and signed,
+ # this means its contents can be read but not tampered with.
+ # Set :encryption_salt if you would also like to encrypt it.
+ plug Plug.Session,
+ store: :cookie,
+ key: "_discuss_key",
+ signing_salt: "b+pDMONc"
+
+ plug Discuss.Router
+end
diff --git a/discuss/lib/discuss/repo.ex b/discuss/lib/discuss/repo.ex
new file mode 100644
index 0000000..359d489
--- /dev/null
+++ b/discuss/lib/discuss/repo.ex
@@ -0,0 +1,3 @@
+defmodule Discuss.Repo do
+ use Ecto.Repo, otp_app: :discuss
+end
diff --git a/discuss/mix.exs b/discuss/mix.exs
new file mode 100644
index 0000000..4c62c37
--- /dev/null
+++ b/discuss/mix.exs
@@ -0,0 +1,56 @@
+defmodule Discuss.Mixfile do
+ use Mix.Project
+
+ def project do
+ [app: :discuss,
+ version: "0.0.1",
+ elixir: "~> 1.2",
+ elixirc_paths: elixirc_paths(Mix.env),
+ compilers: [:phoenix, :gettext] ++ Mix.compilers,
+ build_embedded: Mix.env == :prod,
+ start_permanent: Mix.env == :prod,
+ aliases: aliases(),
+ deps: deps()]
+ end
+
+ # Configuration for the OTP application.
+ #
+ # Type `mix help compile.app` for more information.
+ def application do
+ [mod: {Discuss, []},
+ applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,
+ :phoenix_ecto, :postgrex, :ueberauth, :ueberauth_github]]
+ end
+
+ # Specifies which paths to compile per environment.
+ defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
+ defp elixirc_paths(_), do: ["lib", "web"]
+
+ # Specifies your project dependencies.
+ #
+ # Type `mix help deps` for examples and options.
+ defp deps do
+ [{:phoenix, "~> 1.2.5"},
+ {:phoenix_pubsub, "~> 1.0"},
+ {:phoenix_ecto, "~> 3.0"},
+ {:postgrex, ">= 0.0.0"},
+ {:phoenix_html, "~> 2.6"},
+ {:phoenix_live_reload, "~> 1.0", only: :dev},
+ {:gettext, "~> 0.11"},
+ {:cowboy, "~> 1.0"},
+ {:ueberauth, "~> 0.3"},
+ {:ueberauth_github, "~> 0.4"}]
+ end
+
+ # Aliases are shortcuts or tasks specific to the current project.
+ # For example, to create, migrate and run the seeds file at once:
+ #
+ # $ mix ecto.setup
+ #
+ # See the documentation for `Mix` for more info on aliases.
+ defp aliases do
+ ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
+ "ecto.reset": ["ecto.drop", "ecto.setup"],
+ "test": ["ecto.create --quiet", "ecto.migrate", "test"]]
+ end
+end
diff --git a/discuss/mix.lock b/discuss/mix.lock
new file mode 100644
index 0000000..5f1d652
--- /dev/null
+++ b/discuss/mix.lock
@@ -0,0 +1,30 @@
+%{"certifi": {:hex, :certifi, "0.7.0", "861a57f3808f7eb0c2d1802afeaae0fa5de813b0df0979153cbafcd853ababaf", [:rebar3], []},
+ "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], []},
+ "cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [:rebar3], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
+ "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
+ "db_connection": {:hex, :db_connection, "1.0.0", "63c03e520d54886a66104d34e32397ba960db6e74b596ce221592c07d6a40d8d", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, optional: true]}]},
+ "decimal": {:hex, :decimal, "1.2.0", "462960fd71af282e570f7b477f6be56bf8968e68277d4d0b641a635269bf4b0d", [:mix], []},
+ "ecto": {:hex, :ecto, "2.0.5", "7f4c79ac41ffba1a4c032b69d7045489f0069c256de606523c65d9f8188e502d", [:mix], [{:db_connection, "~> 1.0-rc.4", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.1.2 or ~> 1.2", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.7.7", [hex: :mariaex, optional: true]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.12.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0-beta", [hex: :sbroker, optional: true]}]},
+ "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []},
+ "gettext": {:hex, :gettext, "0.11.0", "80c1dd42d270482418fa158ec5ba073d2980e3718bacad86f3d4ad71d5667679", [:mix], []},
+ "hackney": {:hex, :hackney, "1.6.2", "96a0a5e7e65b7acad8031d231965718cc70a9b4131a8b033b7543bbd673b8210", [:rebar3, :mix], [{:certifi, "0.7.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]},
+ "httpoison": {:hex, :httpoison, "0.9.2", "a211a8e87403a043c41218e64df250d321f236ac57f786c6a0ccf3e9e817c819", [:mix], [{:hackney, "~> 1.6.0", [hex: :hackney, optional: false]}]},
+ "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []},
+ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
+ "mime": {:hex, :mime, "1.1.0", "01c1d6f4083d8aa5c7b8c246ade95139620ef8effb009edde934e0ec3b28090a", [:mix], [], "hexpm"},
+ "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []},
+ "mimetype_parser": {:hex, :mimetype_parser, "0.1.2", "221d2d3f727e89d80de5e1610fc2ce444514aa56f873da1b8fc9c033143e5d6a", [:mix], []},
+ "oauth2": {:hex, :oauth2, "0.6.0", "f3967aba3f358e64fb70046f659f04ea753d7a407ce032046dd048fc2e2e4be3", [:mix], [{:httpoison, "~> 0.7", [hex: :httpoison, optional: false]}, {:mimetype_parser, "~> 0.1", [hex: :mimetype_parser, optional: false]}, {:poison, "~> 1.3 or ~> 2.0", [hex: :poison, optional: false]}]},
+ "phoenix": {:hex, :phoenix, "1.2.5", "dbc45a5f8fb522aaa815b003f2d5598bc45e23102ae3e265768848ab23eafcb7", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.2.4 or ~> 1.1.8 or ~> 1.0.5", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_ecto": {:hex, :phoenix_ecto, "3.0.1", "42eb486ef732cf209d0a353e791806721f33ff40beab0a86f02070a5649ed00a", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, optional: false]}, {:phoenix_html, "~> 2.6", [hex: :phoenix_html, optional: true]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}]},
+ "phoenix_html": {:hex, :phoenix_html, "2.7.0", "19e12e2044340c2e43df206a06d059677c59ea1868bd1c35165438d592cd420b", [:mix], [{:plug, "~> 1.0", [hex: :plug, optional: false]}]},
+ "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.5", "829218c4152ba1e9848e2bf8e161fcde6b4ec679a516259442561d21fde68d0b", [:mix], [{:fs, "~> 0.9.1", [hex: :fs, optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2-rc", [hex: :phoenix, optional: false]}]},
+ "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [:mix], [], "hexpm"},
+ "plug": {:hex, :plug, "1.3.5", "7503bfcd7091df2a9761ef8cecea666d1f2cc454cbbaf0afa0b6e259203b7031", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
+ "poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [:mix], []},
+ "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []},
+ "postgrex": {:hex, :postgrex, "0.12.1", "2f8b46cb3a44dcd42f42938abedbfffe7e103ba4ce810ccbeee8dcf27ca0fb06", [:mix], [{:connection, "~> 1.0", [hex: :connection, optional: false]}, {:db_connection, "~> 1.0-rc.4", [hex: :db_connection, optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, optional: false]}]},
+ "ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [:rebar3], [], "hexpm"},
+ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:rebar, :make], []},
+ "ueberauth": {:hex, :ueberauth, "0.4.0", "bc72d5e5a7bdcbfcf28a756e34630816edabc926303bdce7e171f7ac7ffa4f91", [:mix], [{:plug, "~> 1.2", [hex: :plug, optional: false]}]},
+ "ueberauth_github": {:hex, :ueberauth_github, "0.4.0", "3fe9a20b88c3379bc1eed55f43a6cbf37b4c5e088d565abd07382dc1c99230a2", [:mix], [{:oauth2, "0.6.0", [hex: :oauth2, optional: false]}, {:ueberauth, "~> 0.4", [hex: :ueberauth, optional: false]}]}}
diff --git a/discuss/package.json b/discuss/package.json
new file mode 100644
index 0000000..13de858
--- /dev/null
+++ b/discuss/package.json
@@ -0,0 +1,20 @@
+{
+ "repository": {},
+ "license": "MIT",
+ "scripts": {
+ "deploy": "brunch build --production",
+ "watch": "brunch watch --stdin"
+ },
+ "dependencies": {
+ "phoenix": "file:deps/phoenix",
+ "phoenix_html": "file:deps/phoenix_html"
+ },
+ "devDependencies": {
+ "babel-brunch": "~6.0.0",
+ "brunch": "2.7.4",
+ "clean-css-brunch": "~2.0.0",
+ "css-brunch": "~2.0.0",
+ "javascript-brunch": "~2.0.0",
+ "uglify-js-brunch": "~2.0.1"
+ }
+}
diff --git a/discuss/priv/gettext/en/LC_MESSAGES/errors.po b/discuss/priv/gettext/en/LC_MESSAGES/errors.po
new file mode 100644
index 0000000..087d374
--- /dev/null
+++ b/discuss/priv/gettext/en/LC_MESSAGES/errors.po
@@ -0,0 +1,93 @@
+## `msgid`s in this file come from POT (.pot) files.
+##
+## Do not add, change, or remove `msgid`s manually here as
+## they're tied to the ones in the corresponding POT file
+## (with the same domain).
+##
+## Use `mix gettext.extract --merge` or `mix gettext.merge`
+## to merge POT files into PO files.
+msgid ""
+msgstr ""
+"Language: en\n"
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated to this entry"
+msgstr ""
+
+msgid "are still associated to this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/discuss/priv/gettext/errors.pot b/discuss/priv/gettext/errors.pot
new file mode 100644
index 0000000..a228957
--- /dev/null
+++ b/discuss/priv/gettext/errors.pot
@@ -0,0 +1,91 @@
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated to this entry"
+msgstr ""
+
+msgid "are still associated to this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/discuss/priv/repo/migrations/20161024175806_add_topics.exs b/discuss/priv/repo/migrations/20161024175806_add_topics.exs
new file mode 100644
index 0000000..0c5677e
--- /dev/null
+++ b/discuss/priv/repo/migrations/20161024175806_add_topics.exs
@@ -0,0 +1,9 @@
+defmodule Discuss.Repo.Migrations.AddTopics do
+ use Ecto.Migration
+
+ def change do
+ create table(:topics) do
+ add :title, :string
+ end
+ end
+end
diff --git a/discuss/priv/repo/migrations/20161025223705_add_users.exs b/discuss/priv/repo/migrations/20161025223705_add_users.exs
new file mode 100644
index 0000000..fddfc24
--- /dev/null
+++ b/discuss/priv/repo/migrations/20161025223705_add_users.exs
@@ -0,0 +1,13 @@
+defmodule Discuss.Repo.Migrations.AddUsers do
+ use Ecto.Migration
+
+ def change do
+ create table(:users) do
+ add :email, :string
+ add :provider, :string
+ add :token, :string
+
+ timestamps()
+ end
+ end
+end
diff --git a/discuss/priv/repo/migrations/20161027191357_add_user_id_to_topics.exs b/discuss/priv/repo/migrations/20161027191357_add_user_id_to_topics.exs
new file mode 100644
index 0000000..b05a281
--- /dev/null
+++ b/discuss/priv/repo/migrations/20161027191357_add_user_id_to_topics.exs
@@ -0,0 +1,9 @@
+defmodule Discuss.Repo.Migrations.AddUserIdToTopics do
+ use Ecto.Migration
+
+ def change do
+ alter table(:topics) do
+ add :user_id, references(:users)
+ end
+ end
+end
diff --git a/discuss/priv/repo/migrations/20161027220424_add_comments.exs b/discuss/priv/repo/migrations/20161027220424_add_comments.exs
new file mode 100644
index 0000000..542f89e
--- /dev/null
+++ b/discuss/priv/repo/migrations/20161027220424_add_comments.exs
@@ -0,0 +1,13 @@
+defmodule Discuss.Repo.Migrations.AddComments do
+ use Ecto.Migration
+
+ def change do
+ create table(:comments) do
+ add :content, :string
+ add :user_id, references(:users)
+ add :topic_id, references(:topics)
+
+ timestamps()
+ end
+ end
+end
diff --git a/discuss/priv/repo/seeds.exs b/discuss/priv/repo/seeds.exs
new file mode 100644
index 0000000..aa811bf
--- /dev/null
+++ b/discuss/priv/repo/seeds.exs
@@ -0,0 +1,11 @@
+# Script for populating the database. You can run it as:
+#
+# mix run priv/repo/seeds.exs
+#
+# Inside the script, you can read and write to any of your
+# repositories directly:
+#
+# Discuss.Repo.insert!(%Discuss.SomeModel{})
+#
+# We recommend using the bang functions (`insert!`, `update!`
+# and so on) as they will fail if something goes wrong.
diff --git a/discuss/test/controllers/page_controller_test.exs b/discuss/test/controllers/page_controller_test.exs
new file mode 100644
index 0000000..ea94961
--- /dev/null
+++ b/discuss/test/controllers/page_controller_test.exs
@@ -0,0 +1,8 @@
+defmodule Discuss.PageControllerTest do
+ use Discuss.ConnCase
+
+ test "GET /", %{conn: conn} do
+ conn = get conn, "/"
+ assert html_response(conn, 200) =~ "Welcome to Phoenix!"
+ end
+end
diff --git a/discuss/test/support/channel_case.ex b/discuss/test/support/channel_case.ex
new file mode 100644
index 0000000..71b1126
--- /dev/null
+++ b/discuss/test/support/channel_case.ex
@@ -0,0 +1,43 @@
+defmodule Discuss.ChannelCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ channel tests.
+
+ Such tests rely on `Phoenix.ChannelTest` and also
+ import other functionality to make it easier
+ to build and query models.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with channels
+ use Phoenix.ChannelTest
+
+ alias Discuss.Repo
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+
+
+ # The default endpoint for testing
+ @endpoint Discuss.Endpoint
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Discuss.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Discuss.Repo, {:shared, self()})
+ end
+
+ :ok
+ end
+end
diff --git a/discuss/test/support/conn_case.ex b/discuss/test/support/conn_case.ex
new file mode 100644
index 0000000..80194df
--- /dev/null
+++ b/discuss/test/support/conn_case.ex
@@ -0,0 +1,44 @@
+defmodule Discuss.ConnCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ tests that require setting up a connection.
+
+ Such tests rely on `Phoenix.ConnTest` and also
+ import other functionality to make it easier
+ to build and query models.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with connections
+ use Phoenix.ConnTest
+
+ alias Discuss.Repo
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+
+ import Discuss.Router.Helpers
+
+ # The default endpoint for testing
+ @endpoint Discuss.Endpoint
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Discuss.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Discuss.Repo, {:shared, self()})
+ end
+
+ {:ok, conn: Phoenix.ConnTest.build_conn()}
+ end
+end
diff --git a/discuss/test/support/model_case.ex b/discuss/test/support/model_case.ex
new file mode 100644
index 0000000..9fb3eb0
--- /dev/null
+++ b/discuss/test/support/model_case.ex
@@ -0,0 +1,65 @@
+defmodule Discuss.ModelCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ model tests.
+
+ You may define functions here to be used as helpers in
+ your model tests. See `errors_on/2`'s definition as reference.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ alias Discuss.Repo
+
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+ import Discuss.ModelCase
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Discuss.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Discuss.Repo, {:shared, self()})
+ end
+
+ :ok
+ end
+
+ @doc """
+ Helper for returning list of errors in a struct when given certain data.
+
+ ## Examples
+
+ Given a User schema that lists `:name` as a required field and validates
+ `:password` to be safe, it would return:
+
+ iex> errors_on(%User{}, %{password: "password"})
+ [password: "is unsafe", name: "is blank"]
+
+ You could then write your assertion like:
+
+ assert {:password, "is unsafe"} in errors_on(%User{}, %{password: "password"})
+
+ You can also create the changeset manually and retrieve the errors
+ field directly:
+
+ iex> changeset = User.changeset(%User{}, password: "password")
+ iex> {:password, "is unsafe"} in changeset.errors
+ true
+ """
+ def errors_on(struct, data) do
+ struct.__struct__.changeset(struct, data)
+ |> Ecto.Changeset.traverse_errors(&Discuss.ErrorHelpers.translate_error/1)
+ |> Enum.flat_map(fn {key, errors} -> for msg <- errors, do: {key, msg} end)
+ end
+end
diff --git a/discuss/test/test_helper.exs b/discuss/test/test_helper.exs
new file mode 100644
index 0000000..42e7bf7
--- /dev/null
+++ b/discuss/test/test_helper.exs
@@ -0,0 +1,4 @@
+ExUnit.start
+
+Ecto.Adapters.SQL.Sandbox.mode(Discuss.Repo, :manual)
+
diff --git a/discuss/test/views/error_view_test.exs b/discuss/test/views/error_view_test.exs
new file mode 100644
index 0000000..877b518
--- /dev/null
+++ b/discuss/test/views/error_view_test.exs
@@ -0,0 +1,21 @@
+defmodule Discuss.ErrorViewTest do
+ use Discuss.ConnCase, async: true
+
+ # Bring render/3 and render_to_string/3 for testing custom views
+ import Phoenix.View
+
+ test "renders 404.html" do
+ assert render_to_string(Discuss.ErrorView, "404.html", []) ==
+ "Page not found"
+ end
+
+ test "render 500.html" do
+ assert render_to_string(Discuss.ErrorView, "500.html", []) ==
+ "Internal server error"
+ end
+
+ test "render any other" do
+ assert render_to_string(Discuss.ErrorView, "505.html", []) ==
+ "Internal server error"
+ end
+end
diff --git a/discuss/test/views/layout_view_test.exs b/discuss/test/views/layout_view_test.exs
new file mode 100644
index 0000000..7281361
--- /dev/null
+++ b/discuss/test/views/layout_view_test.exs
@@ -0,0 +1,3 @@
+defmodule Discuss.LayoutViewTest do
+ use Discuss.ConnCase, async: true
+end
diff --git a/discuss/test/views/page_view_test.exs b/discuss/test/views/page_view_test.exs
new file mode 100644
index 0000000..5ac052b
--- /dev/null
+++ b/discuss/test/views/page_view_test.exs
@@ -0,0 +1,3 @@
+defmodule Discuss.PageViewTest do
+ use Discuss.ConnCase, async: true
+end
diff --git a/discuss/web/channels/comments_channel.ex b/discuss/web/channels/comments_channel.ex
new file mode 100644
index 0000000..1f2cd77
--- /dev/null
+++ b/discuss/web/channels/comments_channel.ex
@@ -0,0 +1,32 @@
+defmodule Discuss.CommentsChannel do
+ use Discuss.Web, :channel
+ alias Discuss.{Topic, Comment}
+
+ def join("comments:" <> topic_id, _params, socket) do
+ topic_id = String.to_integer(topic_id)
+ topic = Topic
+ |> Repo.get(topic_id)
+ |> Repo.preload(comments: [:user])
+
+ {:ok, %{comments: topic.comments}, assign(socket, :topic, topic)}
+ end
+
+ def handle_in(name, %{"content" => content}, socket) do
+ topic = socket.assigns.topic
+ user_id = socket.assigns.user_id
+
+ changeset = topic
+ |> build_assoc(:comments, user_id: user_id)
+ |> Comment.changeset(%{content: content})
+
+ case Repo.insert(changeset) do
+ {:ok, comment} ->
+ broadcast!(socket, "comments:#{socket.assigns.topic.id}:new",
+ %{comment: comment}
+ )
+ {:reply, :ok, socket}
+ {:error, _reason} ->
+ {:reply, {:error, %{errors: changeset}}, socket}
+ end
+ end
+end
diff --git a/discuss/web/channels/user_socket.ex b/discuss/web/channels/user_socket.ex
new file mode 100644
index 0000000..ac646ca
--- /dev/null
+++ b/discuss/web/channels/user_socket.ex
@@ -0,0 +1,18 @@
+defmodule Discuss.UserSocket do
+ use Phoenix.Socket
+
+ channel "comments:*", Discuss.CommentsChannel
+
+ transport :websocket, Phoenix.Transports.WebSocket
+
+ def connect(%{"token" => token}, socket) do
+ case Phoenix.Token.verify(socket, "key", token) do
+ {:ok, user_id} ->
+ {:ok, assign(socket, :user_id, user_id)}
+ {:error, _error} ->
+ :error
+ end
+ end
+
+ def id(_socket), do: nil
+end
diff --git a/discuss/web/controllers/auth_controller.ex b/discuss/web/controllers/auth_controller.ex
new file mode 100644
index 0000000..9d4dee2
--- /dev/null
+++ b/discuss/web/controllers/auth_controller.ex
@@ -0,0 +1,42 @@
+defmodule Discuss.AuthController do
+ use Discuss.Web, :controller
+ plug Ueberauth
+
+ alias Discuss.User
+
+ def callback(%{assigns: %{ueberauth_auth: auth}} = conn, params) do
+ user_params = %{token: auth.credentials.token, email: auth.info.email, provider: "github"}
+ changeset = User.changeset(%User{}, user_params)
+
+ signin(conn, changeset)
+ end
+
+ def signout(conn, _params) do
+ conn
+ |> configure_session(drop: true)
+ |> redirect(to: topic_path(conn, :index))
+ end
+
+ defp signin(conn, changeset) do
+ case insert_or_update_user(changeset) do
+ {:ok, user} ->
+ conn
+ |> put_flash(:info, "Welcome back!")
+ |> put_session(:user_id, user.id)
+ |> redirect(to: topic_path(conn, :index))
+ {:error, _reason} ->
+ conn
+ |> put_flash(:error, "Error signing in")
+ |> redirect(to: topic_path(conn, :index))
+ end
+ end
+
+ defp insert_or_update_user(changeset) do
+ case Repo.get_by(User, email: changeset.changes.email) do
+ nil ->
+ Repo.insert(changeset)
+ user ->
+ {:ok, user}
+ end
+ end
+end
diff --git a/discuss/web/controllers/page_controller.ex b/discuss/web/controllers/page_controller.ex
new file mode 100644
index 0000000..9bd91fb
--- /dev/null
+++ b/discuss/web/controllers/page_controller.ex
@@ -0,0 +1,7 @@
+defmodule Discuss.PageController do
+ use Discuss.Web, :controller
+
+ def index(conn, _params) do
+ render conn, "index.html"
+ end
+end
diff --git a/discuss/web/controllers/plugs/require_auth.ex b/discuss/web/controllers/plugs/require_auth.ex
new file mode 100644
index 0000000..16e858f
--- /dev/null
+++ b/discuss/web/controllers/plugs/require_auth.ex
@@ -0,0 +1,20 @@
+defmodule Discuss.Plugs.RequireAuth do
+ import Plug.Conn
+ import Phoenix.Controller
+
+ alias Discuss.Router.Helpers
+
+ def init(_params) do
+ end
+
+ def call(conn, _params) do
+ if conn.assigns[:user] do
+ conn
+ else
+ conn
+ |> put_flash(:error, "You must be logged in.")
+ |> redirect(to: Helpers.topic_path(conn, :index))
+ |> halt()
+ end
+ end
+end
diff --git a/discuss/web/controllers/plugs/set_user.ex b/discuss/web/controllers/plugs/set_user.ex
new file mode 100644
index 0000000..d8b09dc
--- /dev/null
+++ b/discuss/web/controllers/plugs/set_user.ex
@@ -0,0 +1,21 @@
+defmodule Discuss.Plugs.SetUser do
+ import Plug.Conn
+ import Phoenix.Controller
+
+ alias Discuss.Repo
+ alias Discuss.User
+
+ def init(_params) do
+ end
+
+ def call(conn, _params) do
+ user_id = get_session(conn, :user_id)
+
+ cond do
+ user = user_id && Repo.get(User, user_id) ->
+ assign(conn, :user, user)
+ true ->
+ assign(conn, :user, nil)
+ end
+ end
+end
diff --git a/discuss/web/controllers/topic_controller.ex b/discuss/web/controllers/topic_controller.ex
new file mode 100644
index 0000000..ca79fa9
--- /dev/null
+++ b/discuss/web/controllers/topic_controller.ex
@@ -0,0 +1,81 @@
+defmodule Discuss.TopicController do
+ use Discuss.Web, :controller
+
+ alias Discuss.Topic
+
+ plug Discuss.Plugs.RequireAuth when action in [:new, :create, :edit, :update, :delete]
+ plug :check_topic_owner when action in [:update, :edit, :delete]
+
+ def index(conn, _params) do
+ topics = Repo.all(Topic)
+ render conn, "index.html", topics: topics
+ end
+
+ def show(conn, %{"id" => topic_id}) do
+ topic = Repo.get!(Topic, topic_id)
+ render conn, "show.html", topic: topic
+ end
+
+ def new(conn, _params) do
+ changeset = Topic.changeset(%Topic{}, %{})
+
+ render conn, "new.html", changeset: changeset
+ end
+
+ def create(conn, %{"topic" => topic}) do
+ changeset = conn.assigns.user
+ |> build_assoc(:topics)
+ |> Topic.changeset(topic)
+
+ case Repo.insert(changeset) do
+ {:ok, _topic} ->
+ conn
+ |> put_flash(:info, "Topic Created")
+ |> redirect(to: topic_path(conn, :index))
+ {:error, changeset} ->
+ render conn, "new.html", changeset: changeset
+ end
+ end
+
+ def edit(conn, %{"id" => topic_id}) do
+ topic = Repo.get(Topic, topic_id)
+ changeset = Topic.changeset(topic)
+
+ render conn, "edit.html", changeset: changeset, topic: topic
+ end
+
+ def update(conn, %{"id" => topic_id, "topic" => topic}) do
+ old_topic = Repo.get(Topic, topic_id)
+ changeset = Topic.changeset(old_topic, topic)
+
+ case Repo.update(changeset) do
+ {:ok, _topic} ->
+ conn
+ |> put_flash(:info, "Topic Updated")
+ |> redirect(to: topic_path(conn, :index))
+ {:error, changeset} ->
+ render conn, "edit.html", changeset: changeset, topic: old_topic
+ end
+ end
+
+ def delete(conn, %{"id" => topic_id}) do
+ Repo.get!(Topic, topic_id) |> Repo.delete!
+
+ conn
+ |> put_flash(:info, "Topic Deleted")
+ |> redirect(to: topic_path(conn, :index))
+ end
+
+ def check_topic_owner(conn, _params) do
+ %{params: %{"id" => topic_id}} = conn
+
+ if Repo.get(Topic, topic_id).user_id == conn.assigns.user.id do
+ conn
+ else
+ conn
+ |> put_flash(:error, "You cannot edit that")
+ |> redirect(to: topic_path(conn, :index))
+ |> halt()
+ end
+ end
+end
diff --git a/discuss/web/gettext.ex b/discuss/web/gettext.ex
new file mode 100644
index 0000000..3133b99
--- /dev/null
+++ b/discuss/web/gettext.ex
@@ -0,0 +1,24 @@
+defmodule Discuss.Gettext do
+ @moduledoc """
+ A module providing Internationalization with a gettext-based API.
+
+ By using [Gettext](https://hexdocs.pm/gettext),
+ your module gains a set of macros for translations, for example:
+
+ import Discuss.Gettext
+
+ # Simple translation
+ gettext "Here is the string to translate"
+
+ # Plural translation
+ ngettext "Here is the string to translate",
+ "Here are the strings to translate",
+ 3
+
+ # Domain-based translation
+ dgettext "errors", "Here is the error message to translate"
+
+ See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
+ """
+ use Gettext, otp_app: :discuss
+end
diff --git a/discuss/web/models/comment.ex b/discuss/web/models/comment.ex
new file mode 100644
index 0000000..a5f2e88
--- /dev/null
+++ b/discuss/web/models/comment.ex
@@ -0,0 +1,19 @@
+defmodule Discuss.Comment do
+ use Discuss.Web, :model
+
+ @derive {Poison.Encoder, only: [:content, :user]}
+
+ schema "comments" do
+ field :content, :string
+ belongs_to :user, Discuss.User
+ belongs_to :topic, Discuss.Topic
+
+ timestamps()
+ end
+
+ def changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:content])
+ |> validate_required([:content])
+ end
+end
diff --git a/discuss/web/models/topic.ex b/discuss/web/models/topic.ex
new file mode 100644
index 0000000..995132c
--- /dev/null
+++ b/discuss/web/models/topic.ex
@@ -0,0 +1,15 @@
+defmodule Discuss.Topic do
+ use Discuss.Web, :model
+
+ schema "topics" do
+ field :title, :string
+ belongs_to :user, Discuss.User
+ has_many :comments, Discuss.Comment
+ end
+
+ def changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:title])
+ |> validate_required([:title])
+ end
+end
diff --git a/discuss/web/models/user.ex b/discuss/web/models/user.ex
new file mode 100644
index 0000000..08cc8af
--- /dev/null
+++ b/discuss/web/models/user.ex
@@ -0,0 +1,21 @@
+defmodule Discuss.User do
+ use Discuss.Web, :model
+
+ @derive {Poison.Encoder, only: [:email]}
+
+ schema "users" do
+ field :email, :string
+ field :provider, :string
+ field :token, :string
+ has_many :topics, Discuss.Topic
+ has_many :comments, Discuss.Comment
+
+ timestamps()
+ end
+
+ def changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:email, :provider, :token])
+ |> validate_required([:email, :provider, :token])
+ end
+end
diff --git a/discuss/web/router.ex b/discuss/web/router.ex
new file mode 100644
index 0000000..2eee937
--- /dev/null
+++ b/discuss/web/router.ex
@@ -0,0 +1,35 @@
+defmodule Discuss.Router do
+ use Discuss.Web, :router
+
+ pipeline :browser do
+ plug :accepts, ["html"]
+ plug :fetch_session
+ plug :fetch_flash
+ plug :protect_from_forgery
+ plug :put_secure_browser_headers
+ plug Discuss.Plugs.SetUser
+ end
+
+ pipeline :api do
+ plug :accepts, ["json"]
+ end
+
+ scope "/", Discuss do
+ pipe_through :browser # Use the default browser stack
+
+ resources "/", TopicController
+ end
+
+ scope "/auth", Discuss do
+ pipe_through :browser
+
+ get "/signout", AuthController, :signout
+ get "/:provider", AuthController, :request
+ get "/:provider/callback", AuthController, :callback
+ end
+
+ # Other scopes may use custom stacks.
+ # scope "/api", Discuss do
+ # pipe_through :api
+ # end
+end
diff --git a/discuss/web/static/assets/favicon.ico b/discuss/web/static/assets/favicon.ico
new file mode 100644
index 0000000..73de524
Binary files /dev/null and b/discuss/web/static/assets/favicon.ico differ
diff --git a/discuss/web/static/assets/images/phoenix.png b/discuss/web/static/assets/images/phoenix.png
new file mode 100644
index 0000000..9c81075
Binary files /dev/null and b/discuss/web/static/assets/images/phoenix.png differ
diff --git a/discuss/web/static/assets/robots.txt b/discuss/web/static/assets/robots.txt
new file mode 100644
index 0000000..3c9c7c0
--- /dev/null
+++ b/discuss/web/static/assets/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/discuss/web/static/css/app.css b/discuss/web/static/css/app.css
new file mode 100644
index 0000000..84007bf
--- /dev/null
+++ b/discuss/web/static/css/app.css
@@ -0,0 +1,13 @@
+/* This file is for your main application css. */
+
+.help-block {
+ color: red;
+ text-transform: capitalize;
+ position: absolute;
+ top: 37px;
+}
+
+.form-group {
+ position: relative;
+ margin-bottom: 25px;
+}
diff --git a/discuss/web/static/css/phoenix.css b/discuss/web/static/css/phoenix.css
new file mode 100644
index 0000000..df69d80
--- /dev/null
+++ b/discuss/web/static/css/phoenix.css
@@ -0,0 +1,82 @@
+/* Includes Bootstrap as well as some default style for the starter
+ * application. This can be safely deleted to start fresh.
+ */
+
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
+
+/* Space out content a bit */
+body, form, ul, table {
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+/* Phoenix flash messages */
+.alert:empty { display: none; }
+
+/* Phoenix inline forms in links and buttons */
+form.link, form.button {
+ display: inline;
+}
+
+/* Custom page header */
+.header {
+ border-bottom: 1px solid #e5e5e5;
+}
+.logo {
+ width: 519px;
+ height: 71px;
+ display: inline-block;
+ margin-bottom: 1em;
+ background-image: url("/images/phoenix.png");
+ background-size: 519px 71px;
+}
+
+/* Everything but the jumbotron gets side spacing for mobile first views */
+.header,
+.marketing {
+ padding-right: 15px;
+ padding-left: 15px;
+}
+
+/* Customize container */
+@media (min-width: 768px) {
+ .container {
+ max-width: 730px;
+ }
+}
+.container-narrow > hr {
+ margin: 30px 0;
+}
+
+/* Main marketing message */
+.jumbotron {
+ text-align: center;
+ border-bottom: 1px solid #e5e5e5;
+}
+
+/* Supporting marketing content */
+.marketing {
+ margin: 35px 0;
+}
+
+/* Responsive: Portrait tablets and up */
+@media screen and (min-width: 768px) {
+ /* Remove the padding we set earlier */
+ .header,
+ .marketing {
+ padding-right: 0;
+ padding-left: 0;
+ }
+ /* Space out the masthead */
+ .header {
+ margin-bottom: 30px;
+ }
+ /* Remove the bottom border on the jumbotron for visual effect */
+ .jumbotron {
+ border-bottom: 0;
+ }
+}
\ No newline at end of file
diff --git a/discuss/web/static/js/app.js b/discuss/web/static/js/app.js
new file mode 100644
index 0000000..f72263d
--- /dev/null
+++ b/discuss/web/static/js/app.js
@@ -0,0 +1,21 @@
+// Brunch automatically concatenates all files in your
+// watched paths. Those paths can be configured at
+// config.paths.watched in "brunch-config.js".
+//
+// However, those files will only be executed if
+// explicitly imported. The only exception are files
+// in vendor, which are never wrapped in imports and
+// therefore are always executed.
+
+// Import dependencies
+//
+// If you no longer want to use a dependency, remember
+// to also remove its path from "config.paths.watched".
+import "phoenix_html"
+
+// Import local files
+//
+// Local files can be imported directly using relative
+// paths "./socket" or full ones "web/static/js/socket".
+
+import "./socket"
diff --git a/discuss/web/static/js/socket.js b/discuss/web/static/js/socket.js
new file mode 100644
index 0000000..c7209af
--- /dev/null
+++ b/discuss/web/static/js/socket.js
@@ -0,0 +1,57 @@
+import { Socket } from 'phoenix';
+let socket = new Socket('/socket', { params: { token: window.userToken } });
+
+socket.connect();
+
+const createSocket = topicId => {
+ let channel = socket.channel(`comments:${topicId}`, {});
+ channel
+ .join()
+ .receive('ok', resp => {
+ console.log(resp);
+ renderComments(resp.comments);
+ })
+ .receive('error', resp => {
+ console.log('Unable to join', resp);
+ });
+
+ channel.on(`comments:${topicId}:new`, renderComment);
+
+ document.querySelector('button').addEventListener('click', () => {
+ const content = document.querySelector('textarea').value;
+
+ channel.push('comment:add', { content: content });
+ });
+};
+
+function renderComments(comments) {
+ const renderedComments = comments.map(comment => {
+ return commentTemplate(comment);
+ });
+
+ document.querySelector('.collection').innerHTML = renderedComments.join('');
+}
+
+function renderComment(event) {
+ const renderedComment = commentTemplate(event.comment);
+
+ document.querySelector('.collection').innerHTML += renderedComment;
+}
+
+function commentTemplate(comment) {
+ let email = 'Anonymous';
+ if (comment.user) {
+ email = comment.user.email;
+ }
+
+ return `
+
+ ${comment.content}
+
+ ${email}
+
+
+ `;
+}
+
+window.createSocket = createSocket;
diff --git a/discuss/web/templates/layout/app.html.eex b/discuss/web/templates/layout/app.html.eex
new file mode 100644
index 0000000..5122ca9
--- /dev/null
+++ b/discuss/web/templates/layout/app.html.eex
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+ Hello Discuss!
+ ">
+
+
+
+
+
+
+
+
+
+ Discussions
+
+
+ <%= if @conn.assigns[:user] do %>
+
+ <%= link "Sign Out", to: auth_path(@conn, :signout) %>
+
+ <% else %>
+
+ <%= link "Sign in with Github", to: auth_path(@conn, :request, "github") %>
+
+ <% end %>
+
+
+
+
+
+
+
<%= get_flash(@conn, :info) %>
+
<%= get_flash(@conn, :error) %>
+
+
+ <%= render @view_module, @view_template, assigns %>
+
+
+
+
+
+
diff --git a/discuss/web/templates/page/index.html.eex b/discuss/web/templates/page/index.html.eex
new file mode 100644
index 0000000..1152374
--- /dev/null
+++ b/discuss/web/templates/page/index.html.eex
@@ -0,0 +1,39 @@
+
+
<%= gettext "Welcome to %{name}", name: "Phoenix!" %>
+
A productive web framework that does not compromise speed and maintainability.
+
+
+
diff --git a/discuss/web/templates/topic/edit.html.eex b/discuss/web/templates/topic/edit.html.eex
new file mode 100644
index 0000000..70fd339
--- /dev/null
+++ b/discuss/web/templates/topic/edit.html.eex
@@ -0,0 +1,8 @@
+<%= form_for @changeset, topic_path(@conn, :update, @topic), fn f -> %>
+
+ <%= text_input f, :title, placeholder: "Title", class: "form-control" %>
+ <%= error_tag f, :title %>
+
+
+ <%= submit "Save Topic", class: "btn btn-primary" %>
+<% end %>
diff --git a/discuss/web/templates/topic/index.html.eex b/discuss/web/templates/topic/index.html.eex
new file mode 100644
index 0000000..09dfab5
--- /dev/null
+++ b/discuss/web/templates/topic/index.html.eex
@@ -0,0 +1,23 @@
+Topics
+
+
+ <%= for topic <- @topics do %>
+
+ <%= link topic.title, to: topic_path(@conn, :show, topic) %>
+
+ <%= if @conn.assigns.user.id == topic.user_id do %>
+
+ <%= link "Edit", to: topic_path(@conn, :edit, topic) %>
+ <%= link "Delete", to: topic_path(@conn, :delete, topic), method: :delete %>
+
+ <% end %>
+
+ <% end %>
+
+
+
+ <%= link to: topic_path(@conn, :new), class: "btn-floating btn-large waves-effect waves-light red" do %>
+ add
+ <% end %>
+
+
diff --git a/discuss/web/templates/topic/new.html.eex b/discuss/web/templates/topic/new.html.eex
new file mode 100644
index 0000000..820af65
--- /dev/null
+++ b/discuss/web/templates/topic/new.html.eex
@@ -0,0 +1,8 @@
+<%= form_for @changeset, topic_path(@conn, :create), fn f -> %>
+
+ <%= text_input f, :title, placeholder: "Title", class: "form-control" %>
+ <%= error_tag f, :title %>
+
+
+ <%= submit "Save Topic", class: "btn btn-primary" %>
+<% end %>
diff --git a/discuss/web/templates/topic/show.html.eex b/discuss/web/templates/topic/show.html.eex
new file mode 100644
index 0000000..4f59e32
--- /dev/null
+++ b/discuss/web/templates/topic/show.html.eex
@@ -0,0 +1,14 @@
+<%= @topic.title %>
+
+
+
+
diff --git a/discuss/web/views/error_helpers.ex b/discuss/web/views/error_helpers.ex
new file mode 100644
index 0000000..2d09888
--- /dev/null
+++ b/discuss/web/views/error_helpers.ex
@@ -0,0 +1,40 @@
+defmodule Discuss.ErrorHelpers do
+ @moduledoc """
+ Conveniences for translating and building error messages.
+ """
+
+ use Phoenix.HTML
+
+ @doc """
+ Generates tag for inlined form input errors.
+ """
+ def error_tag(form, field) do
+ if error = form.errors[field] do
+ content_tag :span, translate_error(error), class: "help-block"
+ end
+ end
+
+ @doc """
+ Translates an error message using gettext.
+ """
+ def translate_error({msg, opts}) do
+ # Because error messages were defined within Ecto, we must
+ # call the Gettext module passing our Gettext backend. We
+ # also use the "errors" domain as translations are placed
+ # in the errors.po file.
+ # Ecto will pass the :count keyword if the error message is
+ # meant to be pluralized.
+ # On your own code and templates, depending on whether you
+ # need the message to be pluralized or not, this could be
+ # written simply as:
+ #
+ # dngettext "errors", "1 file", "%{count} files", count
+ # dgettext "errors", "is invalid"
+ #
+ if count = opts[:count] do
+ Gettext.dngettext(Discuss.Gettext, "errors", msg, msg, count, opts)
+ else
+ Gettext.dgettext(Discuss.Gettext, "errors", msg, opts)
+ end
+ end
+end
diff --git a/discuss/web/views/error_view.ex b/discuss/web/views/error_view.ex
new file mode 100644
index 0000000..e0baf9e
--- /dev/null
+++ b/discuss/web/views/error_view.ex
@@ -0,0 +1,17 @@
+defmodule Discuss.ErrorView do
+ use Discuss.Web, :view
+
+ def render("404.html", _assigns) do
+ "Page not found"
+ end
+
+ def render("500.html", _assigns) do
+ "Internal server error"
+ end
+
+ # In case no render clause matches or no
+ # template is found, let's render it as 500
+ def template_not_found(_template, assigns) do
+ render "500.html", assigns
+ end
+end
diff --git a/discuss/web/views/layout_view.ex b/discuss/web/views/layout_view.ex
new file mode 100644
index 0000000..29e1136
--- /dev/null
+++ b/discuss/web/views/layout_view.ex
@@ -0,0 +1,3 @@
+defmodule Discuss.LayoutView do
+ use Discuss.Web, :view
+end
diff --git a/discuss/web/views/page_view.ex b/discuss/web/views/page_view.ex
new file mode 100644
index 0000000..81b57c5
--- /dev/null
+++ b/discuss/web/views/page_view.ex
@@ -0,0 +1,3 @@
+defmodule Discuss.PageView do
+ use Discuss.Web, :view
+end
diff --git a/discuss/web/views/topic_view.ex b/discuss/web/views/topic_view.ex
new file mode 100644
index 0000000..4a7df37
--- /dev/null
+++ b/discuss/web/views/topic_view.ex
@@ -0,0 +1,3 @@
+defmodule Discuss.TopicView do
+ use Discuss.Web, :view
+end
diff --git a/discuss/web/web.ex b/discuss/web/web.ex
new file mode 100644
index 0000000..05f684f
--- /dev/null
+++ b/discuss/web/web.ex
@@ -0,0 +1,81 @@
+defmodule Discuss.Web do
+ @moduledoc """
+ A module that keeps using definitions for controllers,
+ views and so on.
+
+ This can be used in your application as:
+
+ use Discuss.Web, :controller
+ use Discuss.Web, :view
+
+ The definitions below will be executed for every view,
+ controller, etc, so keep them short and clean, focused
+ on imports, uses and aliases.
+
+ Do NOT define functions inside the quoted expressions
+ below.
+ """
+
+ def model do
+ quote do
+ use Ecto.Schema
+
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+ end
+ end
+
+ def controller do
+ quote do
+ use Phoenix.Controller
+
+ alias Discuss.Repo
+ import Ecto
+ import Ecto.Query
+
+ import Discuss.Router.Helpers
+ import Discuss.Gettext
+ end
+ end
+
+ def view do
+ quote do
+ use Phoenix.View, root: "web/templates"
+
+ # Import convenience functions from controllers
+ import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
+
+ # Use all HTML functionality (forms, tags, etc)
+ use Phoenix.HTML
+
+ import Discuss.Router.Helpers
+ import Discuss.ErrorHelpers
+ import Discuss.Gettext
+ end
+ end
+
+ def router do
+ quote do
+ use Phoenix.Router
+ end
+ end
+
+ def channel do
+ quote do
+ use Phoenix.Channel
+
+ alias Discuss.Repo
+ import Ecto
+ import Ecto.Query
+ import Discuss.Gettext
+ end
+ end
+
+ @doc """
+ When used, dispatch to the appropriate controller/view/etc.
+ """
+ defmacro __using__(which) when is_atom(which) do
+ apply(__MODULE__, which, [])
+ end
+end
diff --git a/identicon/lib/identicon.ex b/identicon/lib/identicon.ex
index 6dad56f..9a91039 100644
--- a/identicon/lib/identicon.ex
+++ b/identicon/lib/identicon.ex
@@ -4,11 +4,64 @@ defmodule Identicon do
|> hash_input
|> pick_color
|> build_grid
+ |> filter_odd_squares
+ |> build_pixel_map
+ |> draw_image
+ |> save_image(input)
+ end
+
+ def save_image(image, input) do
+ File.write("#{input}.png", image)
+ end
+
+ def draw_image(%Identicon.Image{color: color, pixel_map: pixel_map}) do
+ image = :egd.create(250, 250)
+ fill = :egd.color(color)
+
+ Enum.each pixel_map, fn({start, stop}) ->
+ :egd.filledRectangle(image, start, stop, fill)
+ end
+
+ :egd.render(image)
+ end
+
+ def build_pixel_map(%Identicon.Image{grid: grid} = image) do
+ pixel_map = Enum.map grid, fn({_code, index}) ->
+ horizontal = rem(index, 5) * 50
+ vertical = div(index, 5) * 50
+
+ top_left = {horizontal, vertical}
+ bottom_right = {horizontal + 50, vertical + 50}
+
+ {top_left, bottom_right}
+ end
+
+ %Identicon.Image{image | pixel_map: pixel_map}
+ end
+
+ def filter_odd_squares(%Identicon.Image{grid: grid} = image) do
+ grid = Enum.filter grid, fn({code, _index}) ->
+ rem(code, 2) == 0
+ end
+
+ %Identicon.Image{image | grid: grid}
end
def build_grid(%Identicon.Image{hex: hex} = image) do
- hex
- |> Enum.chunk(3)
+ grid =
+ hex
+ |> Enum.chunk_every(3,3,:discard) # Elixir 1.9 - Enum.chunk/1 superceded. Also required to discard the remaining chunks
+ |> Enum.map(&mirror_row/1)
+ |> List.flatten
+ |> Enum.with_index
+
+ %Identicon.Image{image | grid: grid}
+ end
+
+ def mirror_row(row) do
+ [first, second | _tail] = row
+
+ row ++ [second, first]
end
def pick_color(%Identicon.Image{hex: [r, g, b | _tail]} = image) do
diff --git a/identicon/lib/image.ex b/identicon/lib/image.ex
index 0e8fcbb..f521213 100644
--- a/identicon/lib/image.ex
+++ b/identicon/lib/image.ex
@@ -1,3 +1,3 @@
defmodule Identicon.Image do
- defstruct hex: nil, color: nil
+ defstruct hex: nil, color: nil, grid: nil, pixel_map: nil
end
diff --git a/react-phoenix/.gitignore b/react-phoenix/.gitignore
new file mode 100644
index 0000000..19fe3da
--- /dev/null
+++ b/react-phoenix/.gitignore
@@ -0,0 +1,24 @@
+# App artifacts
+/_build
+/db
+/deps
+/*.ez
+
+# Generated on crash by the VM
+erl_crash.dump
+
+# Static artifacts
+/node_modules
+
+# Since we are building assets from web/static,
+# we ignore priv/static. You may want to comment
+# this depending on your deployment strategy.
+/priv/static/
+
+# The config/prod.secret.exs file by default contains sensitive
+# data and you should not commit it into version control.
+#
+# Alternatively, you may comment the line below and commit the
+# secrets file as long as you replace its contents by environment
+# variables.
+/config/prod.secret.exs
diff --git a/react-phoenix/README.md b/react-phoenix/README.md
new file mode 100644
index 0000000..ffd9e44
--- /dev/null
+++ b/react-phoenix/README.md
@@ -0,0 +1,20 @@
+# Reddit
+
+To start your Phoenix app:
+
+ * Install dependencies with `mix deps.get`
+ * Create and migrate your database with `mix ecto.create && mix ecto.migrate`
+ * Install Node.js dependencies with `npm install`
+ * Start Phoenix endpoint with `mix phoenix.server`
+
+Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
+
+Ready to run in production? Please [check our deployment guides](http://www.phoenixframework.org/docs/deployment).
+
+## Learn more
+
+ * Official website: http://www.phoenixframework.org/
+ * Guides: http://phoenixframework.org/docs/overview
+ * Docs: https://hexdocs.pm/phoenix
+ * Mailing list: http://groups.google.com/group/phoenix-talk
+ * Source: https://github.com/phoenixframework/phoenix
diff --git a/react-phoenix/brunch-config.js b/react-phoenix/brunch-config.js
new file mode 100644
index 0000000..6448faa
--- /dev/null
+++ b/react-phoenix/brunch-config.js
@@ -0,0 +1,70 @@
+exports.config = {
+ // See http://brunch.io/#documentation for docs.
+ files: {
+ javascripts: {
+ joinTo: "js/app.js"
+
+ // To use a separate vendor.js bundle, specify two files path
+ // http://brunch.io/docs/config#-files-
+ // joinTo: {
+ // "js/app.js": /^(web\/static\/js)/,
+ // "js/vendor.js": /^(web\/static\/vendor)|(deps)/
+ // }
+ //
+ // To change the order of concatenation of files, explicitly mention here
+ // order: {
+ // before: [
+ // "web/static/vendor/js/jquery-2.1.1.js",
+ // "web/static/vendor/js/bootstrap.min.js"
+ // ]
+ // }
+ },
+ stylesheets: {
+ joinTo: "css/app.css",
+ order: {
+ after: ["web/static/css/app.css"] // concat app.css last
+ }
+ },
+ templates: {
+ joinTo: "js/app.js"
+ }
+ },
+
+ conventions: {
+ // This option sets where we should place non-css and non-js assets in.
+ // By default, we set this to "/web/static/assets". Files in this directory
+ // will be copied to `paths.public`, which is "priv/static" by default.
+ assets: /^(web\/static\/assets)/
+ },
+
+ // Phoenix paths configuration
+ paths: {
+ // Dependencies and current project directories to watch
+ watched: [
+ "web/static",
+ "test/static"
+ ],
+
+ // Where to compile files to
+ public: "priv/static"
+ },
+
+ // Configure your plugins
+ plugins: {
+ babel: {
+ // Do not use ES6 compiler in vendor code
+ ignore: [/web\/static\/vendor/],
+ presets: ['es2015', 'es2016', 'react']
+ }
+ },
+
+ modules: {
+ autoRequire: {
+ "js/app.js": ["web/static/js/app"]
+ }
+ },
+
+ npm: {
+ enabled: true
+ }
+};
diff --git a/react-phoenix/config/config.exs b/react-phoenix/config/config.exs
new file mode 100644
index 0000000..c679d57
--- /dev/null
+++ b/react-phoenix/config/config.exs
@@ -0,0 +1,36 @@
+# This file is responsible for configuring your application
+# and its dependencies with the aid of the Mix.Config module.
+#
+# This configuration file is loaded before any dependency and
+# is restricted to this project.
+use Mix.Config
+
+# General application configuration
+config :reddit,
+ ecto_repos: [Reddit.Repo]
+
+# Configures the endpoint
+config :reddit, Reddit.Endpoint,
+ url: [host: "localhost"],
+ secret_key_base: "jibgk00xwYBxa0rw2+c5j88L6yzuCRHiQIJCTd3ntJk/nOJCT+lcEMuK9RErgEHW",
+ render_errors: [view: Reddit.ErrorView, accepts: ~w(html json)],
+ pubsub: [name: Reddit.PubSub,
+ adapter: Phoenix.PubSub.PG2]
+
+# Configures Elixir's Logger
+config :logger, :console,
+ format: "$time $metadata[$level] $message\n",
+ metadata: [:request_id]
+
+# Import environment specific config. This must remain at the bottom
+# of this file so it overrides the configuration defined above.
+import_config "#{Mix.env}.exs"
+
+config :ueberauth, Ueberauth,
+ providers: [
+ github: { Ueberauth.Strategy.Github, []}
+ ]
+
+config :ueberauth, Ueberauth.Strategy.Github.OAuth,
+ client_id: "ebf47114a980c0dcc677",
+ client_secret: "5dfe7d3f66f4b467fd878e782dfbe94f8d0b7bde"
diff --git a/react-phoenix/config/dev.exs b/react-phoenix/config/dev.exs
new file mode 100644
index 0000000..12ca856
--- /dev/null
+++ b/react-phoenix/config/dev.exs
@@ -0,0 +1,43 @@
+use Mix.Config
+
+# For development, we disable any cache and enable
+# debugging and code reloading.
+#
+# The watchers configuration can be used to run external
+# watchers to your application. For example, we use it
+# with brunch.io to recompile .js and .css sources.
+config :reddit, Reddit.Endpoint,
+ http: [port: 4000],
+ debug_errors: true,
+ code_reloader: true,
+ check_origin: false,
+ watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
+ cd: Path.expand("../", __DIR__)]]
+
+
+# Watch static and templates for browser reloading.
+config :reddit, Reddit.Endpoint,
+ live_reload: [
+ patterns: [
+ ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
+ ~r{priv/gettext/.*(po)$},
+ ~r{web/views/.*(ex)$},
+ ~r{web/templates/.*(eex)$}
+ ]
+ ]
+
+# Do not include metadata nor timestamps in development logs
+config :logger, :console, format: "[$level] $message\n"
+
+# Set a higher stacktrace during development. Avoid configuring such
+# in production as building large stacktraces may be expensive.
+config :phoenix, :stacktrace_depth, 20
+
+# Configure your database
+config :reddit, Reddit.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "stephengrider",
+ password: "",
+ database: "reddit_dev",
+ hostname: "localhost",
+ pool_size: 10
diff --git a/react-phoenix/config/prod.exs b/react-phoenix/config/prod.exs
new file mode 100644
index 0000000..5f9644b
--- /dev/null
+++ b/react-phoenix/config/prod.exs
@@ -0,0 +1,61 @@
+use Mix.Config
+
+# For production, we configure the host to read the PORT
+# from the system environment. Therefore, you will need
+# to set PORT=80 before running your server.
+#
+# You should also configure the url host to something
+# meaningful, we use this information when generating URLs.
+#
+# Finally, we also include the path to a manifest
+# containing the digested version of static files. This
+# manifest is generated by the mix phoenix.digest task
+# which you typically run after static files are built.
+config :reddit, Reddit.Endpoint,
+ http: [port: {:system, "PORT"}],
+ url: [host: "example.com", port: 80],
+ cache_static_manifest: "priv/static/manifest.json"
+
+# Do not print debug messages in production
+config :logger, level: :info
+
+# ## SSL Support
+#
+# To get SSL working, you will need to add the `https` key
+# to the previous section and set your `:url` port to 443:
+#
+# config :reddit, Reddit.Endpoint,
+# ...
+# url: [host: "example.com", port: 443],
+# https: [port: 443,
+# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
+# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
+#
+# Where those two env variables return an absolute path to
+# the key and cert in disk or a relative path inside priv,
+# for example "priv/ssl/server.key".
+#
+# We also recommend setting `force_ssl`, ensuring no data is
+# ever sent via http, always redirecting to https:
+#
+# config :reddit, Reddit.Endpoint,
+# force_ssl: [hsts: true]
+#
+# Check `Plug.SSL` for all available options in `force_ssl`.
+
+# ## Using releases
+#
+# If you are doing OTP releases, you need to instruct Phoenix
+# to start the server for all endpoints:
+#
+# config :phoenix, :serve_endpoints, true
+#
+# Alternatively, you can configure exactly which server to
+# start per endpoint:
+#
+# config :reddit, Reddit.Endpoint, server: true
+#
+
+# Finally import the config/prod.secret.exs
+# which should be versioned separately.
+import_config "prod.secret.exs"
diff --git a/react-phoenix/config/test.exs b/react-phoenix/config/test.exs
new file mode 100644
index 0000000..2b8843a
--- /dev/null
+++ b/react-phoenix/config/test.exs
@@ -0,0 +1,19 @@
+use Mix.Config
+
+# We don't run a server during test. If one is required,
+# you can enable the server option below.
+config :reddit, Reddit.Endpoint,
+ http: [port: 4001],
+ server: false
+
+# Print only warnings and errors during test
+config :logger, level: :warn
+
+# Configure your database
+config :reddit, Reddit.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "postgres",
+ password: "postgres",
+ database: "reddit_test",
+ hostname: "localhost",
+ pool: Ecto.Adapters.SQL.Sandbox
diff --git a/react-phoenix/lib/reddit.ex b/react-phoenix/lib/reddit.ex
new file mode 100644
index 0000000..b93be8b
--- /dev/null
+++ b/react-phoenix/lib/reddit.ex
@@ -0,0 +1,31 @@
+defmodule Reddit do
+ use Application
+
+ # See http://elixir-lang.org/docs/stable/elixir/Application.html
+ # for more information on OTP Applications
+ def start(_type, _args) do
+ import Supervisor.Spec
+
+ # Define workers and child supervisors to be supervised
+ children = [
+ # Start the Ecto repository
+ supervisor(Reddit.Repo, []),
+ # Start the endpoint when the application starts
+ supervisor(Reddit.Endpoint, []),
+ # Start your own worker by calling: Reddit.Worker.start_link(arg1, arg2, arg3)
+ # worker(Reddit.Worker, [arg1, arg2, arg3]),
+ ]
+
+ # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
+ # for other strategies and supported options
+ opts = [strategy: :one_for_one, name: Reddit.Supervisor]
+ Supervisor.start_link(children, opts)
+ end
+
+ # Tell Phoenix to update the endpoint configuration
+ # whenever the application is updated.
+ def config_change(changed, _new, removed) do
+ Reddit.Endpoint.config_change(changed, removed)
+ :ok
+ end
+end
diff --git a/react-phoenix/lib/reddit/endpoint.ex b/react-phoenix/lib/reddit/endpoint.ex
new file mode 100644
index 0000000..fe60aaa
--- /dev/null
+++ b/react-phoenix/lib/reddit/endpoint.ex
@@ -0,0 +1,42 @@
+defmodule Reddit.Endpoint do
+ use Phoenix.Endpoint, otp_app: :reddit
+
+ socket "/socket", Reddit.UserSocket
+
+ # Serve at "/" the static files from "priv/static" directory.
+ #
+ # You should set gzip to true if you are running phoenix.digest
+ # when deploying your static files in production.
+ plug Plug.Static,
+ at: "/", from: :reddit, gzip: false,
+ only: ~w(css fonts images js favicon.ico robots.txt)
+
+ # Code reloading can be explicitly enabled under the
+ # :code_reloader configuration of your endpoint.
+ if code_reloading? do
+ socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
+ plug Phoenix.LiveReloader
+ plug Phoenix.CodeReloader
+ end
+
+ plug Plug.RequestId
+ plug Plug.Logger
+
+ plug Plug.Parsers,
+ parsers: [:urlencoded, :multipart, :json],
+ pass: ["*/*"],
+ json_decoder: Poison
+
+ plug Plug.MethodOverride
+ plug Plug.Head
+
+ # The session will be stored in the cookie and signed,
+ # this means its contents can be read but not tampered with.
+ # Set :encryption_salt if you would also like to encrypt it.
+ plug Plug.Session,
+ store: :cookie,
+ key: "_reddit_key",
+ signing_salt: "dtbSiNgX"
+
+ plug Reddit.Router
+end
diff --git a/react-phoenix/lib/reddit/repo.ex b/react-phoenix/lib/reddit/repo.ex
new file mode 100644
index 0000000..d41f915
--- /dev/null
+++ b/react-phoenix/lib/reddit/repo.ex
@@ -0,0 +1,3 @@
+defmodule Reddit.Repo do
+ use Ecto.Repo, otp_app: :reddit
+end
diff --git a/react-phoenix/mix.exs b/react-phoenix/mix.exs
new file mode 100644
index 0000000..65961b4
--- /dev/null
+++ b/react-phoenix/mix.exs
@@ -0,0 +1,59 @@
+defmodule Reddit.Mixfile do
+ use Mix.Project
+
+ def project do
+ [app: :reddit,
+ version: "0.0.1",
+ elixir: "~> 1.2",
+ elixirc_paths: elixirc_paths(Mix.env),
+ compilers: [:phoenix, :gettext] ++ Mix.compilers,
+ build_embedded: Mix.env == :prod,
+ start_permanent: Mix.env == :prod,
+ aliases: aliases(),
+ deps: deps()]
+ end
+
+ # Configuration for the OTP application.
+ #
+ # Type `mix help compile.app` for more information.
+ def application do
+ [mod: {Reddit, []},
+ applications: [:phoenix, :phoenix_pubsub, :phoenix_html, :cowboy, :logger, :gettext,
+ :phoenix_ecto, :postgrex, :ueberauth, :ueberauth_github]]
+ end
+
+ # Specifies which paths to compile per environment.
+ defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
+ defp elixirc_paths(_), do: ["lib", "web"]
+
+ # Specifies your project dependencies.
+ #
+ # Type `mix help deps` for examples and options.
+ defp deps do
+ [
+ {:phoenix, "~> 1.2.1"},
+ {:phoenix_pubsub, "~> 1.0"},
+ {:phoenix_ecto, "~> 3.0"},
+ {:postgrex, ">= 0.0.0"},
+ {:phoenix_html, "~> 2.6"},
+ {:phoenix_live_reload, "~> 1.0", only: :dev},
+ {:gettext, "~> 0.11"},
+ {:cowboy, "~> 1.0"},
+ {:mix_test_watch, "~> 0.2", only: :dev},
+ {:ueberauth, "~> 0.3"},
+ {:ueberauth_github, "~> 0.4"}
+ ]
+ end
+
+ # Aliases are shortcuts or tasks specific to the current project.
+ # For example, to create, migrate and run the seeds file at once:
+ #
+ # $ mix ecto.setup
+ #
+ # See the documentation for `Mix` for more info on aliases.
+ defp aliases do
+ ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
+ "ecto.reset": ["ecto.drop", "ecto.setup"],
+ "test": ["ecto.create --quiet", "ecto.migrate", "test"]]
+ end
+end
diff --git a/react-phoenix/mix.lock b/react-phoenix/mix.lock
new file mode 100644
index 0000000..d50a911
--- /dev/null
+++ b/react-phoenix/mix.lock
@@ -0,0 +1,31 @@
+%{"certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []},
+ "connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], []},
+ "cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [:rebar, :make], [{:cowlib, "~> 1.0.0", [hex: :cowlib, optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, optional: false]}]},
+ "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], []},
+ "db_connection": {:hex, :db_connection, "1.0.0-rc.5", "1d9ab6e01387bdf2de7a16c56866971f7c2f75aea7c69cae2a0346e4b537ae0d", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: true]}, {:sbroker, "~> 1.0.0-beta.3", [hex: :sbroker, optional: true]}]},
+ "decimal": {:hex, :decimal, "1.2.0", "462960fd71af282e570f7b477f6be56bf8968e68277d4d0b641a635269bf4b0d", [:mix], []},
+ "ecto": {:hex, :ecto, "2.0.5", "7f4c79ac41ffba1a4c032b69d7045489f0069c256de606523c65d9f8188e502d", [:mix], [{:db_connection, "~> 1.0-rc.4", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.1.2 or ~> 1.2", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.7.7", [hex: :mariaex, optional: true]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.12.0", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0-beta", [hex: :sbroker, optional: true]}]},
+ "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []},
+ "gettext": {:hex, :gettext, "0.11.0", "80c1dd42d270482418fa158ec5ba073d2980e3718bacad86f3d4ad71d5667679", [:mix], []},
+ "hackney": {:hex, :hackney, "1.6.1", "ddd22d42db2b50e6a155439c8811b8f6df61a4395de10509714ad2751c6da817", [:rebar3], [{:certifi, "0.4.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.0", [hex: :ssl_verify_fun, optional: false]}]},
+ "httpoison": {:hex, :httpoison, "0.9.2", "a211a8e87403a043c41218e64df250d321f236ac57f786c6a0ccf3e9e817c819", [:mix], [{:hackney, "~> 1.6.0", [hex: :hackney, optional: false]}]},
+ "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []},
+ "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
+ "mime": {:hex, :mime, "1.0.1", "05c393850524767d13a53627df71beeebb016205eb43bfbd92d14d24ec7a1b51", [:mix], []},
+ "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []},
+ "mimetype_parser": {:hex, :mimetype_parser, "0.1.2", "221d2d3f727e89d80de5e1610fc2ce444514aa56f873da1b8fc9c033143e5d6a", [:mix], []},
+ "mix_test_watch": {:hex, :mix_test_watch, "0.2.6", "9fcc2b1b89d1594c4a8300959c19d50da2f0ff13642c8f681692a6e507f92cab", [:mix], [{:fs, "~> 0.9.1", [hex: :fs, optional: false]}]},
+ "oauth2": {:hex, :oauth2, "0.6.0", "f3967aba3f358e64fb70046f659f04ea753d7a407ce032046dd048fc2e2e4be3", [:mix], [{:httpoison, "~> 0.7", [hex: :httpoison, optional: false]}, {:mimetype_parser, "~> 0.1", [hex: :mimetype_parser, optional: false]}, {:poison, "~> 1.3 or ~> 2.0", [hex: :poison, optional: false]}]},
+ "phoenix": {:hex, :phoenix, "1.2.1", "6dc592249ab73c67575769765b66ad164ad25d83defa3492dc6ae269bd2a68ab", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, optional: false]}, {:plug, "~> 1.1", [hex: :plug, optional: false]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: false]}]},
+ "phoenix_ecto": {:hex, :phoenix_ecto, "3.0.1", "42eb486ef732cf209d0a353e791806721f33ff40beab0a86f02070a5649ed00a", [:mix], [{:ecto, "~> 2.0", [hex: :ecto, optional: false]}, {:phoenix_html, "~> 2.6", [hex: :phoenix_html, optional: true]}, {:plug, "~> 1.0", [hex: :plug, optional: false]}]},
+ "phoenix_html": {:hex, :phoenix_html, "2.7.0", "19e12e2044340c2e43df206a06d059677c59ea1868bd1c35165438d592cd420b", [:mix], [{:plug, "~> 1.0", [hex: :plug, optional: false]}]},
+ "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.0.5", "829218c4152ba1e9848e2bf8e161fcde6b4ec679a516259442561d21fde68d0b", [:mix], [{:fs, "~> 0.9.1", [hex: :fs, optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2-rc", [hex: :phoenix, optional: false]}]},
+ "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.0", "c31af4be22afeeebfaf246592778c8c840e5a1ddc7ca87610c41ccfb160c2c57", [:mix], []},
+ "plug": {:hex, :plug, "1.2.0", "496bef96634a49d7803ab2671482f0c5ce9ce0b7b9bc25bc0ae8e09859dd2004", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}, {:mime, "~> 1.0", [hex: :mime, optional: false]}]},
+ "poison": {:hex, :poison, "2.2.0", "4763b69a8a77bd77d26f477d196428b741261a761257ff1cf92753a0d4d24a63", [:mix], []},
+ "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []},
+ "postgrex": {:hex, :postgrex, "0.12.0", "bdeeb4c42768c47c3c92228e66c70357fe9a9384fbc9de06abba774b22dd0635", [:mix], [{:connection, "~> 1.0", [hex: :connection, optional: false]}, {:db_connection, "~> 1.0-rc.4", [hex: :db_connection, optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, optional: false]}]},
+ "ranch": {:hex, :ranch, "1.2.1", "a6fb992c10f2187b46ffd17ce398ddf8a54f691b81768f9ef5f461ea7e28c762", [:make], []},
+ "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.0", "edee20847c42e379bf91261db474ffbe373f8acb56e9079acb6038d4e0bf414f", [:rebar, :make], []},
+ "ueberauth": {:hex, :ueberauth, "0.4.0", "bc72d5e5a7bdcbfcf28a756e34630816edabc926303bdce7e171f7ac7ffa4f91", [:mix], [{:plug, "~> 1.2", [hex: :plug, optional: false]}]},
+ "ueberauth_github": {:hex, :ueberauth_github, "0.4.0", "3fe9a20b88c3379bc1eed55f43a6cbf37b4c5e088d565abd07382dc1c99230a2", [:mix], [{:oauth2, "0.6.0", [hex: :oauth2, optional: false]}, {:ueberauth, "~> 0.4", [hex: :ueberauth, optional: false]}]}}
diff --git a/react-phoenix/package-lock.json b/react-phoenix/package-lock.json
new file mode 100644
index 0000000..0e1c8d3
--- /dev/null
+++ b/react-phoenix/package-lock.json
@@ -0,0 +1,2894 @@
+{
+ "lockfileVersion": 1,
+ "dependencies": {
+ "accepts": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz",
+ "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=",
+ "dev": true
+ },
+ "acorn": {
+ "version": "4.0.13",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+ "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=",
+ "dev": true
+ },
+ "align-text": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+ "dev": true
+ },
+ "amdefine": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
+ "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "ansicolors": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz",
+ "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
+ "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
+ "dev": true
+ },
+ "anysort": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/anysort/-/anysort-1.0.1.tgz",
+ "integrity": "sha1-NBvV1boUhfZOVa6GXx1FmUtQf8Q=",
+ "dev": true
+ },
+ "arr-diff": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
+ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
+ "dev": true
+ },
+ "arr-flatten": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
+ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+ "dev": true
+ },
+ "array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=",
+ "dev": true
+ },
+ "array-unique": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
+ "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
+ "dev": true
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "asn1.js": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.1.tgz",
+ "integrity": "sha1-SLokC0WpKA6UdImQull9IWYX/UA=",
+ "dev": true
+ },
+ "assert": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.3.0.tgz",
+ "integrity": "sha1-A5OaYiWCqBLMICMgoLmlbJuBWEk=",
+ "dev": true
+ },
+ "async": {
+ "version": "0.2.10",
+ "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz",
+ "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=",
+ "dev": true
+ },
+ "async-each": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
+ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
+ "dev": true
+ },
+ "babel-brunch": {
+ "version": "6.0.6",
+ "resolved": "https://registry.npmjs.org/babel-brunch/-/babel-brunch-6.0.6.tgz",
+ "integrity": "sha1-QVw/3HfZuYKB0uFfPzNSwPSBjG4=",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true
+ },
+ "babel-core": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
+ "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
+ "dev": true
+ },
+ "babel-generator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz",
+ "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=",
+ "dev": true
+ },
+ "babel-helper-builder-binary-assignment-operator-visitor": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
+ "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=",
+ "dev": true
+ },
+ "babel-helper-builder-react-jsx": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz",
+ "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=",
+ "dev": true
+ },
+ "babel-helper-call-delegate": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz",
+ "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=",
+ "dev": true
+ },
+ "babel-helper-define-map": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz",
+ "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=",
+ "dev": true
+ },
+ "babel-helper-explode-assignable-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz",
+ "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=",
+ "dev": true
+ },
+ "babel-helper-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
+ "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=",
+ "dev": true
+ },
+ "babel-helper-get-function-arity": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz",
+ "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=",
+ "dev": true
+ },
+ "babel-helper-hoist-variables": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz",
+ "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=",
+ "dev": true
+ },
+ "babel-helper-optimise-call-expression": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz",
+ "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=",
+ "dev": true
+ },
+ "babel-helper-regex": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz",
+ "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=",
+ "dev": true
+ },
+ "babel-helper-replace-supers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz",
+ "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=",
+ "dev": true
+ },
+ "babel-helpers": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz",
+ "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=",
+ "dev": true
+ },
+ "babel-messages": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz",
+ "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=",
+ "dev": true
+ },
+ "babel-plugin-check-es2015-constants": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz",
+ "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=",
+ "dev": true
+ },
+ "babel-plugin-syntax-exponentiation-operator": {
+ "version": "6.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+ "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
+ "dev": true
+ },
+ "babel-plugin-syntax-flow": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
+ "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=",
+ "dev": true
+ },
+ "babel-plugin-syntax-jsx": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
+ "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-arrow-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
+ "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-block-scoped-functions": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz",
+ "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-block-scoping": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz",
+ "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-classes": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz",
+ "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-computed-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz",
+ "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-destructuring": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz",
+ "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-duplicate-keys": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz",
+ "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-for-of": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz",
+ "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-function-name": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz",
+ "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz",
+ "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-amd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz",
+ "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-commonjs": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz",
+ "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-systemjs": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz",
+ "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-modules-umd": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz",
+ "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-object-super": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz",
+ "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-parameters": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz",
+ "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-shorthand-properties": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz",
+ "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-spread": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz",
+ "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-sticky-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz",
+ "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-template-literals": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz",
+ "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-typeof-symbol": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz",
+ "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=",
+ "dev": true
+ },
+ "babel-plugin-transform-es2015-unicode-regex": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz",
+ "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=",
+ "dev": true
+ },
+ "babel-plugin-transform-exponentiation-operator": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz",
+ "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=",
+ "dev": true
+ },
+ "babel-plugin-transform-flow-strip-types": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz",
+ "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=",
+ "dev": true
+ },
+ "babel-plugin-transform-react-display-name": {
+ "version": "6.25.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz",
+ "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=",
+ "dev": true
+ },
+ "babel-plugin-transform-react-jsx": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz",
+ "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=",
+ "dev": true
+ },
+ "babel-plugin-transform-react-jsx-self": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz",
+ "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=",
+ "dev": true
+ },
+ "babel-plugin-transform-react-jsx-source": {
+ "version": "6.22.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz",
+ "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=",
+ "dev": true
+ },
+ "babel-plugin-transform-regenerator": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz",
+ "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=",
+ "dev": true
+ },
+ "babel-plugin-transform-strict-mode": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz",
+ "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=",
+ "dev": true
+ },
+ "babel-preset-es2015": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz",
+ "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
+ "dev": true
+ },
+ "babel-preset-es2016": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-es2016/-/babel-preset-es2016-6.24.1.tgz",
+ "integrity": "sha1-+QC/k+LrwNJ235uKtZck6/2Vn4s=",
+ "dev": true
+ },
+ "babel-preset-flow": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz",
+ "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=",
+ "dev": true
+ },
+ "babel-preset-react": {
+ "version": "6.24.1",
+ "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz",
+ "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=",
+ "dev": true
+ },
+ "babel-register": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
+ "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=",
+ "dev": true,
+ "dependencies": {
+ "core-js": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz",
+ "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=",
+ "dev": true
+ }
+ }
+ },
+ "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=",
+ "dev": true,
+ "dependencies": {
+ "core-js": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz",
+ "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=",
+ "dev": true
+ }
+ }
+ },
+ "babel-template": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz",
+ "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=",
+ "dev": true
+ },
+ "babel-traverse": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz",
+ "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=",
+ "dev": true
+ },
+ "babel-types": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+ "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+ "dev": true
+ },
+ "babylon": {
+ "version": "6.18.0",
+ "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+ "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "base64-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz",
+ "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz",
+ "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=",
+ "dev": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
+ "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo="
+ },
+ "bn.js": {
+ "version": "4.11.8",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==",
+ "dev": true
+ },
+ "bower-config": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/bower-config/-/bower-config-1.4.0.tgz",
+ "integrity": "sha1-FsOMETX4BxwZ8lk41hsNjL8Y0/E=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
+ "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI="
+ },
+ "braces": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
+ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
+ "dev": true
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=",
+ "dev": true
+ },
+ "browser-resolve": {
+ "version": "1.11.2",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz",
+ "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=",
+ "dev": true
+ },
+ "browserify-aes": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.0.8.tgz",
+ "integrity": "sha512-WYCMOT/PtGTlpOKFht0YJFYcPy6pLCR98CtWfzK13zoynLlBMvAdEMSRGmgnJCw2M2j/5qxBkinZQFobieM8dQ==",
+ "dev": true
+ },
+ "browserify-cipher": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz",
+ "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=",
+ "dev": true
+ },
+ "browserify-des": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz",
+ "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=",
+ "dev": true
+ },
+ "browserify-rsa": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+ "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
+ "dev": true
+ },
+ "browserify-sign": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz",
+ "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=",
+ "dev": true
+ },
+ "brunch": {
+ "version": "2.7.4",
+ "resolved": "https://registry.npmjs.org/brunch/-/brunch-2.7.4.tgz",
+ "integrity": "sha1-lhs95x/Gsuy7zwi19XhZXAdSdJo=",
+ "dev": true,
+ "dependencies": {
+ "debug": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
+ "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
+ "dev": true
+ },
+ "ms": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
+ "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
+ "dev": true
+ }
+ }
+ },
+ "brunch-skeletons": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/brunch-skeletons/-/brunch-skeletons-0.1.6.tgz",
+ "integrity": "sha512-x5ASPnG5yKyJFxJsCOydNPezP/YEyk4fB8GH9pdQA8sK2tFIO+RR0zzQ34Fs0y6AGcQJvx1FZvNjqW4f3Q5M3w==",
+ "dev": true
+ },
+ "buffer": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.3.1.tgz",
+ "integrity": "sha1-DmX9Acw+kVTRUvazyTS1uKG2czw=",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-2.0.0.tgz",
+ "integrity": "sha1-byIAO6rPADzNKHr+aHIVH93FhXk=",
+ "dev": true
+ },
+ "camelcase": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+ "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=",
+ "dev": true
+ },
+ "center-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true
+ },
+ "check-dependencies": {
+ "version": "0.12.3",
+ "resolved": "https://registry.npmjs.org/check-dependencies/-/check-dependencies-0.12.3.tgz",
+ "integrity": "sha1-a6ST1CIdvD9pURM1OuRjj3csXHU=",
+ "dev": true,
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "chokidar": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.4.3.tgz",
+ "integrity": "sha1-X+czpNmsrqUbJkVLfllVkWPQ27I=",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true
+ },
+ "clean-css": {
+ "version": "3.4.28",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
+ "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
+ "dev": true,
+ "dependencies": {
+ "commander": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
+ "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
+ "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
+ "dev": true
+ }
+ }
+ },
+ "clean-css-brunch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/clean-css-brunch/-/clean-css-brunch-2.0.0.tgz",
+ "integrity": "sha1-N8J0dsRwigCUzWRsnEZKwZcMSxc=",
+ "dev": true
+ },
+ "cliui": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+ "dev": true,
+ "dependencies": {
+ "wordwrap": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=",
+ "dev": true
+ }
+ }
+ },
+ "coffee-script": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.10.0.tgz",
+ "integrity": "sha1-EpOLz5vhlI+gBvkuDEyegXBRCMA=",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz",
+ "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=",
+ "dev": true
+ },
+ "commonjs-require-definition": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/commonjs-require-definition/-/commonjs-require-definition-0.5.0.tgz",
+ "integrity": "sha1-CfGLn8+xxQh1JYPf/P1q/g87eJM=",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "connect-slashes": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/connect-slashes/-/connect-slashes-1.3.1.tgz",
+ "integrity": "sha1-ldYYMND51YU8hojwtfQ5iLGGrDc=",
+ "dev": true
+ },
+ "content-disposition": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz",
+ "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=",
+ "dev": true
+ },
+ "content-type": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.2.tgz",
+ "integrity": "sha1-t9ETrueo3Se9IRM8TcJSnfFyHu0=",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz",
+ "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=",
+ "dev": true
+ },
+ "cookie": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz",
+ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=",
+ "dev": true
+ },
+ "cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=",
+ "dev": true
+ },
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
+ "dev": true
+ },
+ "create-ecdh": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz",
+ "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=",
+ "dev": true
+ },
+ "create-hash": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz",
+ "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=",
+ "dev": true
+ },
+ "create-hmac": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz",
+ "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=",
+ "dev": true
+ },
+ "create-react-class": {
+ "version": "15.6.0",
+ "resolved": "https://registry.npmjs.org/create-react-class/-/create-react-class-15.6.0.tgz",
+ "integrity": "sha1-q0SEl8JlZuHilBPogyB9V8/nvtQ="
+ },
+ "crypto-browserify": {
+ "version": "3.11.1",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.11.1.tgz",
+ "integrity": "sha512-Na7ZlwCOqoaW5RwUK1WpXws2kv8mNhWdTlzob0UXulk6G9BDbyiJaGTYBIX61Ozn9l1EPPJpICZb4DaOpT9NlQ==",
+ "dev": true
+ },
+ "css-brunch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/css-brunch/-/css-brunch-2.0.0.tgz",
+ "integrity": "sha1-pMa+x9f2yPpHaacu6Vz9/FDFQVc=",
+ "dev": true
+ },
+ "debug": {
+ "version": "2.6.8",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
+ "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=",
+ "dev": true
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true
+ },
+ "deep-assign": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-2.0.0.tgz",
+ "integrity": "sha1-6+BrHwfwja5ZdiDj3RYi83GhxXI=",
+ "dev": true
+ },
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
+ "dev": true
+ },
+ "depd": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz",
+ "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=",
+ "dev": true
+ },
+ "deppack": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/deppack/-/deppack-0.4.4.tgz",
+ "integrity": "sha1-QRqphjbAEaGkfTX7RcG/gBC+RiU=",
+ "dev": true
+ },
+ "des.js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz",
+ "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=",
+ "dev": true
+ },
+ "destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=",
+ "dev": true
+ },
+ "detect-file": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz",
+ "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=",
+ "dev": true
+ },
+ "detect-indent": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
+ "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=",
+ "dev": true
+ },
+ "detective": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-4.5.0.tgz",
+ "integrity": "sha1-blqMaybmx6JUsca210kNmOyR7dE=",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz",
+ "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=",
+ "dev": true
+ },
+ "domain-browser": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.1.7.tgz",
+ "integrity": "sha1-hnqksJP6oF8d4IwG9NeyH9+GmLw=",
+ "dev": true
+ },
+ "ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz",
+ "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=",
+ "dev": true
+ },
+ "encodeurl": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz",
+ "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=",
+ "dev": true
+ },
+ "encoding": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz",
+ "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "esprima": {
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
+ "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "etag": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.0.tgz",
+ "integrity": "sha1-b2Ma7zNtbEY2K1F2QETOIWvjwFE=",
+ "dev": true
+ },
+ "events": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
+ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=",
+ "dev": true
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true
+ },
+ "expand-brackets": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
+ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
+ "dev": true
+ },
+ "expand-range": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
+ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
+ "dev": true
+ },
+ "expand-tilde": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz",
+ "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=",
+ "dev": true
+ },
+ "express": {
+ "version": "4.15.4",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz",
+ "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=",
+ "dev": true
+ },
+ "extglob": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
+ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz",
+ "integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=",
+ "dev": true
+ },
+ "fbjs": {
+ "version": "0.8.14",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.14.tgz",
+ "integrity": "sha1-0dviviVMNakeCfMfnNUKQLKg7Rw="
+ },
+ "fcache": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/fcache/-/fcache-0.1.1.tgz",
+ "integrity": "sha1-KGIQm5L+D2iz0RvAsGYyR1Az05w=",
+ "dev": true
+ },
+ "filename-regex": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
+ "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
+ "dev": true
+ },
+ "fill-range": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz",
+ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=",
+ "dev": true
+ },
+ "finalhandler": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.0.4.tgz",
+ "integrity": "sha512-16l/r8RgzlXKmFOhZpHBztvye+lAhC5SU7hXavnerC9UfZqZxxXl3BzL8MhffPT3kF61lj9Oav2LKEzh0ei7tg==",
+ "dev": true
+ },
+ "findup-sync": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz",
+ "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=",
+ "dev": true
+ },
+ "for-in": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
+ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
+ "dev": true
+ },
+ "for-own": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
+ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
+ "dev": true
+ },
+ "forwarded": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.0.tgz",
+ "integrity": "sha1-Ge+YdMSuHCl7zweP3mOgm2aoQ2M=",
+ "dev": true
+ },
+ "fresh": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.0.tgz",
+ "integrity": "sha1-9HTKXmqSRtb9jglTz6m5yAWvp44=",
+ "dev": true
+ },
+ "fs-exists-sync": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz",
+ "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "fsevents": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz",
+ "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "abbrev": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ajv": {
+ "version": "4.11.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "bundled": true,
+ "dev": true
+ },
+ "aproba": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "are-we-there-yet": {
+ "version": "1.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "asn1": {
+ "version": "0.2.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "assert-plus": {
+ "version": "0.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aws-sign2": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "aws4": {
+ "version": "1.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "balanced-match": {
+ "version": "0.4.2",
+ "bundled": true,
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "block-stream": {
+ "version": "0.0.9",
+ "bundled": true,
+ "dev": true
+ },
+ "boom": {
+ "version": "2.10.1",
+ "bundled": true,
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.7",
+ "bundled": true,
+ "dev": true
+ },
+ "buffer-shims": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "co": {
+ "version": "4.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "code-point-at": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "combined-stream": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "console-control-strings": {
+ "version": "1.1.0",
+ "bundled": true,
+ "dev": true
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "cryptiles": {
+ "version": "2.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "debug": {
+ "version": "2.6.8",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "deep-extend": {
+ "version": "0.4.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "delegates": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "ecc-jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "extend": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "extsprintf": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "form-data": {
+ "version": "2.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "bundled": true,
+ "dev": true
+ },
+ "fstream-ignore": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "gauge": {
+ "version": "2.7.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "glob": {
+ "version": "7.1.2",
+ "bundled": true,
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "bundled": true,
+ "dev": true
+ },
+ "har-schema": {
+ "version": "1.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "har-validator": {
+ "version": "4.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "has-unicode": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "hawk": {
+ "version": "3.1.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "hoek": {
+ "version": "2.16.3",
+ "bundled": true,
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "bundled": true,
+ "dev": true
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "bundled": true,
+ "dev": true
+ },
+ "ini": {
+ "version": "1.3.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jodid25519": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-schema": {
+ "version": "0.2.3",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-stable-stringify": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "jsprim": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.27.0",
+ "bundled": true,
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.15",
+ "bundled": true,
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "bundled": true,
+ "dev": true
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "bundled": true,
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "bundled": true,
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "node-pre-gyp": {
+ "version": "0.6.36",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "nopt": {
+ "version": "4.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "npmlog": {
+ "version": "4.1.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "oauth-sign": {
+ "version": "0.8.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "bundled": true,
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "performance-now": {
+ "version": "0.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "bundled": true,
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "qs": {
+ "version": "6.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rc": {
+ "version": "1.2.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "readable-stream": {
+ "version": "2.2.9",
+ "bundled": true,
+ "dev": true
+ },
+ "request": {
+ "version": "2.81.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "bundled": true,
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "semver": {
+ "version": "5.3.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "signal-exit": {
+ "version": "3.0.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sntp": {
+ "version": "1.0.9",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "sshpk": {
+ "version": "1.13.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "assert-plus": {
+ "version": "1.0.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ }
+ }
+ },
+ "string_decoder": {
+ "version": "1.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "string-width": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "stringstream": {
+ "version": "0.0.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "2.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "bundled": true,
+ "dev": true
+ },
+ "tar-pack": {
+ "version": "3.4.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tough-cookie": {
+ "version": "2.3.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "uid-number": {
+ "version": "0.0.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ },
+ "uuid": {
+ "version": "3.0.1",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "verror": {
+ "version": "1.3.6",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wide-align": {
+ "version": "1.1.2",
+ "bundled": true,
+ "dev": true,
+ "optional": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "bundled": true,
+ "dev": true
+ }
+ }
+ },
+ "fstream": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
+ "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE="
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ=="
+ },
+ "glob-base": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
+ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
+ "dev": true
+ },
+ "glob-parent": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
+ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
+ "dev": true
+ },
+ "global-modules": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz",
+ "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=",
+ "dev": true
+ },
+ "global-prefix": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz",
+ "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=",
+ "dev": true
+ },
+ "globals": {
+ "version": "9.18.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
+ "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+ "dev": true
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
+ },
+ "graceful-readlink": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
+ "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz",
+ "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=",
+ "dev": true
+ },
+ "hammerjs": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
+ "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true
+ },
+ "hash-base": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz",
+ "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=",
+ "dev": true
+ },
+ "hash.js": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz",
+ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==",
+ "dev": true
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=",
+ "dev": true
+ },
+ "home-or-tmp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz",
+ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=",
+ "dev": true
+ },
+ "homedir-polyfill": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz",
+ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=",
+ "dev": true
+ },
+ "hosted-git-info": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.1.5.tgz",
+ "integrity": "sha1-C6gdkNouJas0ozLm7HeTbhWYEYs=",
+ "dev": true
+ },
+ "http-errors": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz",
+ "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=",
+ "dev": true
+ },
+ "https-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-0.0.1.tgz",
+ "integrity": "sha1-P5E2XKvmC3ftDruiS0VOPgnZWoI=",
+ "dev": true
+ },
+ "iconv-lite": {
+ "version": "0.4.18",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz",
+ "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA=="
+ },
+ "ieee754": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz",
+ "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=",
+ "dev": true
+ },
+ "indexof": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz",
+ "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk="
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "ini": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz",
+ "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=",
+ "dev": true
+ },
+ "init-skeleton": {
+ "version": "0.9.5",
+ "resolved": "https://registry.npmjs.org/init-skeleton/-/init-skeleton-0.9.5.tgz",
+ "integrity": "sha1-q6I9xFUXI2xUg25Nc27ULy1JTto=",
+ "dev": true
+ },
+ "invariant": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz",
+ "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=",
+ "dev": true
+ },
+ "ipaddr.js": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.4.0.tgz",
+ "integrity": "sha1-KWrKh4qCGBbluF0KKFqZvP9FgvA=",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
+ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
+ "dev": true
+ },
+ "is-buffer": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz",
+ "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=",
+ "dev": true
+ },
+ "is-dotfile": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
+ "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
+ "dev": true
+ },
+ "is-equal-shallow": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
+ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
+ "dev": true
+ },
+ "is-extendable": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
+ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
+ "dev": true
+ },
+ "is-extglob": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
+ "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
+ "dev": true
+ },
+ "is-finite": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz",
+ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
+ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
+ "dev": true
+ },
+ "is-number": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
+ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
+ "dev": true
+ },
+ "is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
+ "dev": true
+ },
+ "is-posix-bracket": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
+ "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
+ "dev": true
+ },
+ "is-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
+ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
+ "dev": true
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
+ },
+ "is-windows": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz",
+ "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=",
+ "dev": true
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true
+ },
+ "isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk="
+ },
+ "javascript-brunch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/javascript-brunch/-/javascript-brunch-2.0.0.tgz",
+ "integrity": "sha1-gx4db6j/XeyysIcgJPGtRHuWPOA=",
+ "dev": true
+ },
+ "jquery": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz",
+ "integrity": "sha1-LInWiJterFIqfuoywUUhVZxsvwI="
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls="
+ },
+ "jsesc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+ "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
+ "dev": true
+ },
+ "json5": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+ "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=",
+ "dev": true
+ },
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true
+ },
+ "lazy-cache": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=",
+ "dev": true
+ },
+ "lodash": {
+ "version": "4.17.4",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
+ "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+ "dev": true
+ },
+ "loggy": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/loggy/-/loggy-0.3.5.tgz",
+ "integrity": "sha1-M/EoAbH2Bjlm6nnZtqJduPy8QQc=",
+ "dev": true
+ },
+ "longest": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+ "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=",
+ "dev": true
+ },
+ "loose-envify": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
+ "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg="
+ },
+ "materialize-css": {
+ "version": "0.97.8",
+ "resolved": "https://registry.npmjs.org/materialize-css/-/materialize-css-0.97.8.tgz",
+ "integrity": "sha1-45ziBWeFsMTpzUhHws3xU+GcR88="
+ },
+ "md5.js": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz",
+ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=",
+ "dev": true,
+ "dependencies": {
+ "hash-base": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
+ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=",
+ "dev": true
+ }
+ }
+ },
+ "media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "dev": true
+ },
+ "merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=",
+ "dev": true
+ },
+ "methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "dev": true
+ },
+ "micro-promisify": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/micro-promisify/-/micro-promisify-0.1.1.tgz",
+ "integrity": "sha1-Bx2lkLSVZWDe30qucERynBookC0=",
+ "dev": true
+ },
+ "micromatch": {
+ "version": "2.3.11",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
+ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
+ "dev": true
+ },
+ "miller-rabin": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.0.tgz",
+ "integrity": "sha1-SmL7HUKTPAVYOYL0xxb2+55sbT0=",
+ "dev": true
+ },
+ "mime": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz",
+ "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=",
+ "dev": true
+ },
+ "mime-db": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz",
+ "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.17",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz",
+ "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=",
+ "dev": true
+ },
+ "minimalistic-assert": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz",
+ "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA=="
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM="
+ },
+ "mout": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/mout/-/mout-1.0.0.tgz",
+ "integrity": "sha1-m98dSvV9ZtR8s1OmM1oygQmOFQE=",
+ "dev": true
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "nan": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz",
+ "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=",
+ "dev": true,
+ "optional": true
+ },
+ "ncp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+ "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
+ "dev": true
+ },
+ "negotiator": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
+ "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=",
+ "dev": true
+ },
+ "node-archiver": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/node-archiver/-/node-archiver-0.3.0.tgz",
+ "integrity": "sha1-ufGv5QBtC98pJgGBgzoHCXi8aUc="
+ },
+ "node-browser-modules": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/node-browser-modules/-/node-browser-modules-0.1.0.tgz",
+ "integrity": "sha1-QZPLtw9UJ1ml5ObWsBzLY46Zoaw=",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ }
+ }
+ },
+ "node-fetch": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.2.tgz",
+ "integrity": "sha512-xZZUq2yDhKMIn/UgG5q//IZSNLJIwW2QxS14CNH5spuiXkITM2pUitjdq58yLSaU7m4M0wBNaM2Gh/ggY4YJig=="
+ },
+ "normalize-git-url": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/normalize-git-url/-/normalize-git-url-3.0.2.tgz",
+ "integrity": "sha1-jl8Uvgva7bc+ByADEKpBbCc1D8Q=",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true
+ },
+ "number-is-nan": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
+ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+ "dev": true
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
+ },
+ "object.omit": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
+ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
+ "dev": true
+ },
+ "on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E="
+ },
+ "optimist": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
+ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
+ "dev": true
+ },
+ "os-browserify": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.2.1.tgz",
+ "integrity": "sha1-Y/xMzuXS13Y9Jrv4YBB45sLgBE8=",
+ "dev": true
+ },
+ "os-homedir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
+ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
+ "dev": true
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
+ "dev": true
+ },
+ "osenv": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz",
+ "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=",
+ "dev": true
+ },
+ "parse-asn1": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz",
+ "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=",
+ "dev": true
+ },
+ "parse-glob": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
+ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
+ "dev": true
+ },
+ "parse-passwd": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
+ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
+ "dev": true
+ },
+ "parseurl": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.1.tgz",
+ "integrity": "sha1-yKuMkiO6NIiKpkopeyiFO+wY2lY=",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz",
+ "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "path-to-regexp": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
+ "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=",
+ "dev": true
+ },
+ "pbkdf2": {
+ "version": "3.0.13",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz",
+ "integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==",
+ "dev": true
+ },
+ "phoenix": {
+ "version": "file:deps/phoenix"
+ },
+ "phoenix_html": {
+ "version": "file:deps/phoenix_html"
+ },
+ "preserve": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
+ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
+ "dev": true
+ },
+ "private": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz",
+ "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="
+ },
+ "prop-types": {
+ "version": "15.5.10",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz",
+ "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ="
+ },
+ "proxy-addr": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-1.1.5.tgz",
+ "integrity": "sha1-ccDuOxAt4/IC87ZPYI0XP8uhqRg=",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz",
+ "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=",
+ "dev": true
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
+ "dev": true
+ },
+ "pushserve": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pushserve/-/pushserve-1.0.2.tgz",
+ "integrity": "sha1-/fuAOTnKM3UtOPLRqpdawBqTJT8=",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.0.tgz",
+ "integrity": "sha512-fjVFjW9yhqMhVGwRExCXLhJKrLlkYSaxNWdyc9rmHlrVZbk35YHH312dFd7191uQeXkI3mKLZTIbSvIeFwFemg==",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
+ "dev": true
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=",
+ "dev": true
+ },
+ "quickly-copy-file": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/quickly-copy-file/-/quickly-copy-file-1.0.0.tgz",
+ "integrity": "sha1-n4/wZiMFEO50IrASFHKwk6hpCFk=",
+ "dev": true
+ },
+ "randomatic": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
+ "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+ "dev": true,
+ "dependencies": {
+ "is-number": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
+ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
+ "dev": true,
+ "dependencies": {
+ "kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true
+ }
+ }
+ },
+ "kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true
+ }
+ }
+ },
+ "randombytes": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.5.tgz",
+ "integrity": "sha512-8T7Zn1AhMsQ/HI1SjcCfT/t4ii3eAqco3yOcSzS4mozsOz69lHLsoMXmF9nZgnFanYscnSlUSgs8uZyKzpE6kg==",
+ "dev": true
+ },
+ "range-parser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz",
+ "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=",
+ "dev": true
+ },
+ "react": {
+ "version": "15.6.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-15.6.1.tgz",
+ "integrity": "sha1-uqhDTsZ4C96ZfNw4C3nNM7ljk98="
+ },
+ "react-dom": {
+ "version": "15.6.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-15.6.1.tgz",
+ "integrity": "sha1-LLDtQZEDjlPCCes6eaI+Kkz5lHA="
+ },
+ "read-components": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/read-components/-/read-components-0.7.0.tgz",
+ "integrity": "sha1-d9znrctypRQkDEemdbm896NQndk=",
+ "dev": true
+ },
+ "readable-stream": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
+ "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
+ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
+ "dev": true
+ },
+ "regenerate": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz",
+ "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=",
+ "dev": true
+ },
+ "regenerator-runtime": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz",
+ "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz",
+ "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==",
+ "dev": true
+ },
+ "regex-cache": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
+ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+ "dev": true
+ },
+ "regexpu-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz",
+ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=",
+ "dev": true
+ },
+ "regjsgen": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+ "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz",
+ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=",
+ "dev": true,
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true
+ }
+ }
+ },
+ "remove-trailing-separator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+ "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
+ "dev": true
+ },
+ "repeat-element": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz",
+ "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=",
+ "dev": true
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
+ "dev": true
+ },
+ "repeating": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz",
+ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
+ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
+ "dev": true
+ },
+ "resolve-dir": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz",
+ "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=",
+ "dev": true
+ },
+ "right-align": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz",
+ "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0="
+ },
+ "ripemd160": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz",
+ "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=",
+ "dev": true
+ },
+ "safe-buffer": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
+ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+ "dev": true
+ },
+ "semver": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
+ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
+ "dev": true
+ },
+ "send": {
+ "version": "0.15.4",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.15.4.tgz",
+ "integrity": "sha1-mF+qPihLAnPHkzZKNcZze9k5Bbk=",
+ "dev": true
+ },
+ "serve-brunch": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/serve-brunch/-/serve-brunch-0.1.2.tgz",
+ "integrity": "sha1-F55xN0j7qT5lCJLSV4gijTNr3Dw=",
+ "dev": true
+ },
+ "serve-static": {
+ "version": "1.12.4",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.12.4.tgz",
+ "integrity": "sha1-m2qpjutyU8Tu3Ewfb9vKYJkBqWE=",
+ "dev": true
+ },
+ "set-immediate-shim": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
+ "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
+ "dev": true
+ },
+ "setimmediate": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
+ "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU="
+ },
+ "setprototypeof": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz",
+ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.8",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.8.tgz",
+ "integrity": "sha1-NwaMLEdra69ALRSknGf1l5IfY08=",
+ "dev": true
+ },
+ "since-app-start": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/since-app-start/-/since-app-start-0.1.0.tgz",
+ "integrity": "sha1-SHUBUCD5D8q4/l3jMi+pWdVAa0Q=",
+ "dev": true
+ },
+ "skemata": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/skemata/-/skemata-0.1.2.tgz",
+ "integrity": "sha1-88UhAptnvm4IJfDfhn7peRbeRTA=",
+ "dev": true
+ },
+ "slash": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
+ "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.4.17",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.17.tgz",
+ "integrity": "sha512-30c1Ch8FSjV0FwC253iftbbj0dU/OXoSg1LAEGZJUlGgjTNj6cu+DVqJWWIZJY5RXLWV4eFtR+4ouo0VIOYOTg==",
+ "dev": true
+ },
+ "statuses": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz",
+ "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
+ "dev": true
+ },
+ "stream-http": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.1.1.tgz",
+ "integrity": "sha1-O4gDA7q+A21va0MSfU3Nb4iT4ds=",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
+ "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ },
+ "tar": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
+ "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE="
+ },
+ "timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha1-ycWLV1voQHN1y14kYtrO50NZ9B0=",
+ "dev": true
+ },
+ "to-arraybuffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
+ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=",
+ "dev": true
+ },
+ "to-fast-properties": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+ "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=",
+ "dev": true
+ },
+ "trim-right": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
+ "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=",
+ "dev": true
+ },
+ "true-case-path": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz",
+ "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=",
+ "dev": true,
+ "dependencies": {
+ "glob": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
+ "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
+ "dev": true
+ }
+ }
+ },
+ "tty-browserify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
+ "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=",
+ "dev": true
+ },
+ "type-is": {
+ "version": "1.6.15",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz",
+ "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=",
+ "dev": true
+ },
+ "ua-parser-js": {
+ "version": "0.7.14",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.14.tgz",
+ "integrity": "sha1-EQ1T+kw/MmwSEpK76skE0uAzh8o="
+ },
+ "uglify-js": {
+ "version": "2.6.4",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.4.tgz",
+ "integrity": "sha1-ZeovswWck5RpLxX+2HwrNsFrmt8=",
+ "dev": true
+ },
+ "uglify-js-brunch": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/uglify-js-brunch/-/uglify-js-brunch-2.0.1.tgz",
+ "integrity": "sha1-v1W6KN9eTuUIO/fjlk2I60qryhM=",
+ "dev": true
+ },
+ "uglify-to-browserify": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+ "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+ "dev": true
+ },
+ "unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "dev": true
+ },
+ "untildify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz",
+ "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=",
+ "dev": true
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
+ "dev": true,
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
+ "dev": true
+ }
+ }
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
+ "dev": true,
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=",
+ "dev": true
+ }
+ }
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
+ "dev": true
+ },
+ "utils-merge": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz",
+ "integrity": "sha1-ApT7kiu5N1FTVBxPcJYjHyh8ivg=",
+ "dev": true
+ },
+ "vary": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.1.tgz",
+ "integrity": "sha1-Z1Neu2lMHVIldFeYRmUyP1h+jTc=",
+ "dev": true
+ },
+ "vm-browserify": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz",
+ "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=",
+ "dev": true
+ },
+ "whatwg-fetch": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz",
+ "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ="
+ },
+ "which": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
+ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+ "dev": true
+ },
+ "window-size": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=",
+ "dev": true
+ },
+ "wordwrap": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
+ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "xtend": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
+ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
+ "dev": true
+ },
+ "yargs": {
+ "version": "3.10.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+ "dev": true
+ }
+ }
+}
diff --git a/react-phoenix/package.json b/react-phoenix/package.json
new file mode 100644
index 0000000..2b208a9
--- /dev/null
+++ b/react-phoenix/package.json
@@ -0,0 +1,24 @@
+{
+ "repository": {},
+ "license": "MIT",
+ "scripts": {
+ "deploy": "brunch build --production",
+ "watch": "brunch watch --stdin"
+ },
+ "dependencies": {
+ "materialize-css": "^0.97.7",
+ "phoenix": "file:deps/phoenix",
+ "phoenix_html": "file:deps/phoenix_html",
+ "react": "^15.3.2",
+ "react-dom": "^15.3.2"
+ },
+ "devDependencies": {
+ "babel-brunch": "~6.0.0",
+ "babel-preset-react": "^6.16.0",
+ "brunch": "2.7.4",
+ "clean-css-brunch": "~2.0.0",
+ "css-brunch": "~2.0.0",
+ "javascript-brunch": "~2.0.0",
+ "uglify-js-brunch": "~2.0.1"
+ }
+}
diff --git a/react-phoenix/priv/gettext/en/LC_MESSAGES/errors.po b/react-phoenix/priv/gettext/en/LC_MESSAGES/errors.po
new file mode 100644
index 0000000..087d374
--- /dev/null
+++ b/react-phoenix/priv/gettext/en/LC_MESSAGES/errors.po
@@ -0,0 +1,93 @@
+## `msgid`s in this file come from POT (.pot) files.
+##
+## Do not add, change, or remove `msgid`s manually here as
+## they're tied to the ones in the corresponding POT file
+## (with the same domain).
+##
+## Use `mix gettext.extract --merge` or `mix gettext.merge`
+## to merge POT files into PO files.
+msgid ""
+msgstr ""
+"Language: en\n"
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated to this entry"
+msgstr ""
+
+msgid "are still associated to this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/react-phoenix/priv/gettext/errors.pot b/react-phoenix/priv/gettext/errors.pot
new file mode 100644
index 0000000..a228957
--- /dev/null
+++ b/react-phoenix/priv/gettext/errors.pot
@@ -0,0 +1,91 @@
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated to this entry"
+msgstr ""
+
+msgid "are still associated to this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/react-phoenix/priv/repo/migrations/20160927181632_create_user.exs b/react-phoenix/priv/repo/migrations/20160927181632_create_user.exs
new file mode 100644
index 0000000..ed3c7f4
--- /dev/null
+++ b/react-phoenix/priv/repo/migrations/20160927181632_create_user.exs
@@ -0,0 +1,14 @@
+defmodule Reddit.Repo.Migrations.CreateUser do
+ use Ecto.Migration
+
+ def change do
+ create table(:users) do
+ add :email, :string
+ add :provider, :string
+ add :token, :string
+
+ timestamps()
+ end
+
+ end
+end
diff --git a/react-phoenix/priv/repo/migrations/20160929203558_add_posts.exs b/react-phoenix/priv/repo/migrations/20160929203558_add_posts.exs
new file mode 100644
index 0000000..7becddf
--- /dev/null
+++ b/react-phoenix/priv/repo/migrations/20160929203558_add_posts.exs
@@ -0,0 +1,12 @@
+defmodule Reddit.Repo.Migrations.AddPosts do
+ use Ecto.Migration
+
+ def change do
+ create table(:posts) do
+ add :title, :string
+ add :user_id, references(:users)
+
+ timestamps
+ end
+ end
+end
diff --git a/react-phoenix/priv/repo/migrations/20160929203753_comments.exs b/react-phoenix/priv/repo/migrations/20160929203753_comments.exs
new file mode 100644
index 0000000..928f236
--- /dev/null
+++ b/react-phoenix/priv/repo/migrations/20160929203753_comments.exs
@@ -0,0 +1,13 @@
+defmodule Reddit.Repo.Migrations.Comments do
+ use Ecto.Migration
+
+ def change do
+ create table(:comments) do
+ add :content, :string
+ add :user_id, references(:users)
+ add :post_id, references(:posts)
+
+ timestamps
+ end
+ end
+end
diff --git a/react-phoenix/priv/repo/seeds.exs b/react-phoenix/priv/repo/seeds.exs
new file mode 100644
index 0000000..df65a51
--- /dev/null
+++ b/react-phoenix/priv/repo/seeds.exs
@@ -0,0 +1,11 @@
+# Script for populating the database. You can run it as:
+#
+# mix run priv/repo/seeds.exs
+#
+# Inside the script, you can read and write to any of your
+# repositories directly:
+#
+# Reddit.Repo.insert!(%Reddit.SomeModel{})
+#
+# We recommend using the bang functions (`insert!`, `update!`
+# and so on) as they will fail if something goes wrong.
diff --git a/react-phoenix/test/controllers/post_controller_test.exs b/react-phoenix/test/controllers/post_controller_test.exs
new file mode 100644
index 0000000..97f2708
--- /dev/null
+++ b/react-phoenix/test/controllers/post_controller_test.exs
@@ -0,0 +1,58 @@
+defmodule Reddit.PostControllerTest do
+ use Reddit.ConnCase
+
+ alias Reddit.{Post}
+ @valid_attrs %{title: "some content"}
+ @invalid_attrs %{}
+
+ setup %{conn: conn} do
+ user = create_user
+ conn = assign(conn, :user, user)
+
+ post =
+ user
+ |> build_assoc(:posts)
+ |> Repo.insert!
+
+ {:ok, %{conn: conn, post: post, user: user}}
+ end
+
+ test "renders form for new resources", %{conn: conn} do
+ conn = get conn, post_path(conn, :new)
+ assert html_response(conn, 200) =~ "Create Post"
+ end
+
+ test "creates resource when data is valid", %{conn: conn} do
+ post conn, post_path(conn, :create), post: @valid_attrs
+ assert Repo.get_by(Post, @valid_attrs)
+ end
+
+ test "does not create resource and renders errors when data is invalid", %{conn: conn} do
+ post_count = length(Repo.all(Post))
+
+ post conn, post_path(conn, :create), post: @invalid_attrs
+ assert post_count == length(Repo.all(Post))
+ end
+
+ test "renders form for editing chosen resource", %{conn: conn, post: post} do
+ conn = get conn, post_path(conn, :edit, post)
+ assert html_response(conn, 200) =~ "Create Post"
+ end
+
+ test "updates chosen resource and redirects when data is valid", %{conn: conn, post: post} do
+ put conn, post_path(conn, :update, post), post: @valid_attrs
+ assert Repo.get_by(Post, @valid_attrs)
+ end
+
+ test "redirects when a user who doesnt own a post edits it", %{conn: conn} do
+ post = Repo.insert! %Post{}
+ conn = put conn, post_path(conn, :update, post), post: @valid_attrs
+ assert html_response(conn, 302)
+ end
+
+ test "deletes chosen resource", %{conn: conn, post: post} do
+ conn = delete conn, post_path(conn, :delete, post)
+ assert redirected_to(conn) == post_path(conn, :index)
+ refute Repo.get(Post, post.id)
+ end
+end
diff --git a/react-phoenix/test/controllers/session_controller_test.exs b/react-phoenix/test/controllers/session_controller_test.exs
new file mode 100644
index 0000000..e4848d7
--- /dev/null
+++ b/react-phoenix/test/controllers/session_controller_test.exs
@@ -0,0 +1,48 @@
+defmodule Reddit.SessionControllerTest do
+ use Reddit.ConnCase
+ alias Reddit.SessionController
+ alias Reddit.User
+
+ @auth %{
+ info: %{email: "test@test.com"},
+ credentials: %{token: "123"}
+ }
+
+ def signup(conn) do
+ conn
+ |> bypass_through(Reddit.Router, :browser)
+ |> get("/")
+ |> assign(:ueberauth_auth, @auth)
+ |> SessionController.callback(%{"provider" => "github"})
+ end
+
+ test "signing in creates a new account", %{conn: conn} do
+ user_count = length(Repo.all(User))
+ signup(conn)
+
+ assert user_count + 1 == length(Repo.all(User))
+ end
+
+ test "signing in creates a session", %{conn: conn} do
+ conn = signup(conn)
+ assert get_session(conn, :user_id)
+ end
+
+ test "signing out redirects to index", %{conn: conn} do
+ conn = signup(conn)
+ conn = get conn, session_path(conn, :signout)
+
+ assert redirected_to(conn) == "/"
+ end
+
+ test "oauthing twice doesnt create two accounts", %{conn: conn} do
+ user_count = length(Repo.all(User))
+ conn = signup(conn)
+ conn = get conn, session_path(conn, :signout)
+ conn
+ |> recycle
+ |> signup
+
+ assert user_count + 1 == length(Repo.all(User))
+ end
+end
diff --git a/react-phoenix/test/models/post_test.exs b/react-phoenix/test/models/post_test.exs
new file mode 100644
index 0000000..31cceb1
--- /dev/null
+++ b/react-phoenix/test/models/post_test.exs
@@ -0,0 +1,18 @@
+defmodule Reddit.PostTest do
+ use Reddit.ModelCase
+
+ alias Reddit.Post
+
+ @valid_attrs %{title: "some content"}
+ @invalid_attrs %{}
+
+ test "changeset with valid attributes" do
+ changeset = Post.changeset(%Post{}, @valid_attrs)
+ assert changeset.valid?
+ end
+
+ test "changeset with invalid attributes" do
+ changeset = Post.changeset(%Post{}, @invalid_attrs)
+ refute changeset.valid?
+ end
+end
diff --git a/react-phoenix/test/models/user_test.exs b/react-phoenix/test/models/user_test.exs
new file mode 100644
index 0000000..2c1d298
--- /dev/null
+++ b/react-phoenix/test/models/user_test.exs
@@ -0,0 +1,18 @@
+defmodule Reddit.UserTest do
+ use Reddit.ModelCase
+
+ alias Reddit.User
+
+ @valid_attrs %{provider: "some content", token: "some content", email: "some content"}
+ @invalid_attrs %{}
+
+ test "changeset with valid attributes" do
+ changeset = User.changeset(%User{}, @valid_attrs)
+ assert changeset.valid?
+ end
+
+ test "changeset with invalid attributes" do
+ changeset = User.changeset(%User{}, @invalid_attrs)
+ refute changeset.valid?
+ end
+end
diff --git a/react-phoenix/test/support/channel_case.ex b/react-phoenix/test/support/channel_case.ex
new file mode 100644
index 0000000..1bc6fdb
--- /dev/null
+++ b/react-phoenix/test/support/channel_case.ex
@@ -0,0 +1,43 @@
+defmodule Reddit.ChannelCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ channel tests.
+
+ Such tests rely on `Phoenix.ChannelTest` and also
+ import other functionality to make it easier
+ to build and query models.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with channels
+ use Phoenix.ChannelTest
+
+ alias Reddit.Repo
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+
+
+ # The default endpoint for testing
+ @endpoint Reddit.Endpoint
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Reddit.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Reddit.Repo, {:shared, self()})
+ end
+
+ :ok
+ end
+end
diff --git a/react-phoenix/test/support/conn_case.ex b/react-phoenix/test/support/conn_case.ex
new file mode 100644
index 0000000..dd6ff5d
--- /dev/null
+++ b/react-phoenix/test/support/conn_case.ex
@@ -0,0 +1,45 @@
+defmodule Reddit.ConnCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ tests that require setting up a connection.
+
+ Such tests rely on `Phoenix.ConnTest` and also
+ import other functionality to make it easier
+ to build and query models.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with connections
+ use Phoenix.ConnTest
+
+ alias Reddit.Repo
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+
+ import Reddit.Router.Helpers
+ import Reddit.ModelHelpers
+
+ # The default endpoint for testing
+ @endpoint Reddit.Endpoint
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Reddit.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Reddit.Repo, {:shared, self()})
+ end
+
+ {:ok, conn: Phoenix.ConnTest.build_conn()}
+ end
+end
diff --git a/react-phoenix/test/support/model_case.ex b/react-phoenix/test/support/model_case.ex
new file mode 100644
index 0000000..88dea87
--- /dev/null
+++ b/react-phoenix/test/support/model_case.ex
@@ -0,0 +1,65 @@
+defmodule Reddit.ModelCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ model tests.
+
+ You may define functions here to be used as helpers in
+ your model tests. See `errors_on/2`'s definition as reference.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ alias Reddit.Repo
+
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+ import Reddit.ModelCase
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Reddit.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Reddit.Repo, {:shared, self()})
+ end
+
+ :ok
+ end
+
+ @doc """
+ Helper for returning list of errors in a struct when given certain data.
+
+ ## Examples
+
+ Given a User schema that lists `:name` as a required field and validates
+ `:password` to be safe, it would return:
+
+ iex> errors_on(%User{}, %{password: "password"})
+ [password: "is unsafe", name: "is blank"]
+
+ You could then write your assertion like:
+
+ assert {:password, "is unsafe"} in errors_on(%User{}, %{password: "password"})
+
+ You can also create the changeset manually and retrieve the errors
+ field directly:
+
+ iex> changeset = User.changeset(%User{}, password: "password")
+ iex> {:password, "is unsafe"} in changeset.errors
+ true
+ """
+ def errors_on(struct, data) do
+ struct.__struct__.changeset(struct, data)
+ |> Ecto.Changeset.traverse_errors(&Reddit.ErrorHelpers.translate_error/1)
+ |> Enum.flat_map(fn {key, errors} -> for msg <- errors, do: {key, msg} end)
+ end
+end
diff --git a/react-phoenix/test/support/model_helpers.ex b/react-phoenix/test/support/model_helpers.ex
new file mode 100644
index 0000000..a1b21e9
--- /dev/null
+++ b/react-phoenix/test/support/model_helpers.ex
@@ -0,0 +1,31 @@
+defmodule Reddit.ModelHelpers do
+ import Plug.Conn, only: [assign: 3, put_session: 3]
+ alias Reddit.User
+ alias Reddit.Repo
+
+ # def login_user(conn, params \\ %{}) do
+ # {:ok, user} = create_user(params)
+ #
+ # conn =
+ # conn
+ # |> put_session(:user_id, user.id)
+ # |> assign(:user, user)
+ #
+ # {conn, user}
+ # end
+
+ def create_user(params \\ %{}) do
+ params = Map.merge(%{
+ email: "test@test.com",
+ provider: "github",
+ token: "12345"
+ }, params)
+
+ {:ok, user} =
+ %User{}
+ |> User.changeset(params)
+ |> Repo.insert
+
+ user
+ end
+end
diff --git a/react-phoenix/test/test_helper.exs b/react-phoenix/test/test_helper.exs
new file mode 100644
index 0000000..3857a2e
--- /dev/null
+++ b/react-phoenix/test/test_helper.exs
@@ -0,0 +1,4 @@
+ExUnit.start
+
+Ecto.Adapters.SQL.Sandbox.mode(Reddit.Repo, :manual)
+
diff --git a/react-phoenix/test/views/error_view_test.exs b/react-phoenix/test/views/error_view_test.exs
new file mode 100644
index 0000000..c7ce8c1
--- /dev/null
+++ b/react-phoenix/test/views/error_view_test.exs
@@ -0,0 +1,21 @@
+defmodule Reddit.ErrorViewTest do
+ use Reddit.ConnCase, async: true
+
+ # Bring render/3 and render_to_string/3 for testing custom views
+ import Phoenix.View
+
+ test "renders 404.html" do
+ assert render_to_string(Reddit.ErrorView, "404.html", []) ==
+ "Page not found"
+ end
+
+ test "render 500.html" do
+ assert render_to_string(Reddit.ErrorView, "500.html", []) ==
+ "Internal server error"
+ end
+
+ test "render any other" do
+ assert render_to_string(Reddit.ErrorView, "505.html", []) ==
+ "Internal server error"
+ end
+end
diff --git a/react-phoenix/test/views/layout_view_test.exs b/react-phoenix/test/views/layout_view_test.exs
new file mode 100644
index 0000000..732b42c
--- /dev/null
+++ b/react-phoenix/test/views/layout_view_test.exs
@@ -0,0 +1,3 @@
+defmodule Reddit.LayoutViewTest do
+ use Reddit.ConnCase, async: true
+end
diff --git a/react-phoenix/test/views/page_view_test.exs b/react-phoenix/test/views/page_view_test.exs
new file mode 100644
index 0000000..616ef94
--- /dev/null
+++ b/react-phoenix/test/views/page_view_test.exs
@@ -0,0 +1,3 @@
+defmodule Reddit.PageViewTest do
+ use Reddit.ConnCase, async: true
+end
diff --git a/react-phoenix/web/channels/comments_channel.ex b/react-phoenix/web/channels/comments_channel.ex
new file mode 100644
index 0000000..4a7513c
--- /dev/null
+++ b/react-phoenix/web/channels/comments_channel.ex
@@ -0,0 +1,38 @@
+defmodule Reddit.CommentsChannel do
+ use Reddit.Web, :channel
+ alias Reddit.{Post, Comment, User}
+
+ def join("comments:" <> post_id, _params, socket) do
+ post_id = String.to_integer(post_id)
+ post =
+ Post
+ |> Repo.get(post_id)
+ |> Repo.preload(:comments)
+
+ comments = render_comments(post.comments)
+
+ {:ok, %{comments: comments}, assign(socket, :post, post)}
+ end
+
+ def handle_in("comment:add", %{"content" => content}, socket) do
+ user = Repo.get(User, socket.assigns.user_id)
+
+ changeset =
+ socket.assigns.post
+ |> build_assoc(:comments)
+ |> Comment.changeset(%{content: content})
+
+ case Repo.insert(changeset) do
+ {:ok, comment} ->
+ broadcast! socket, "comments:#{socket.assigns.post.id}:new",
+ %{comments: render_comments([comment])}
+ {:reply, :ok, socket}
+ {:error, _reason} ->
+ {:reply, {:error, %{errors: changeset}}, socket}
+ end
+ end
+
+ defp render_comments(comments) do
+ Phoenix.View.render_many(comments, Reddit.CommentView, "comments.json")
+ end
+end
diff --git a/react-phoenix/web/channels/user_socket.ex b/react-phoenix/web/channels/user_socket.ex
new file mode 100644
index 0000000..ca4869b
--- /dev/null
+++ b/react-phoenix/web/channels/user_socket.ex
@@ -0,0 +1,23 @@
+defmodule Reddit.UserSocket do
+ use Phoenix.Socket
+
+ ## Channels
+ channel "comments:*", Reddit.CommentsChannel
+
+ transport :websocket, Phoenix.Transports.WebSocket
+
+ @max_age 2 * 7 * 24 * 60 * 60
+
+ def connect(%{"auth_token" => token}, socket) do
+ token = Phoenix.Token.verify(socket, "user_socket", token)
+
+ case token do
+ {:ok, user_id} ->
+ {:ok, assign(socket, :user_id, user_id)}
+ {:error, _error} ->
+ :error
+ end
+ end
+
+ def id(_socket), do: nil
+end
diff --git a/react-phoenix/web/controllers/comment_controller.ex b/react-phoenix/web/controllers/comment_controller.ex
new file mode 100644
index 0000000..e69de29
diff --git a/react-phoenix/web/controllers/helpers/queries.ex b/react-phoenix/web/controllers/helpers/queries.ex
new file mode 100644
index 0000000..cab38b6
--- /dev/null
+++ b/react-phoenix/web/controllers/helpers/queries.ex
@@ -0,0 +1,10 @@
+defmodule Reddit.Queries do
+ import Ecto.Query
+ alias Reddit.{Topic, Post, User, Repo}
+
+ def topics_for_posts(topic_id) do
+ topic = Topic
+ |> Repo.get(topic_id)
+ |> Repo.preload(:posts)
+ end
+end
diff --git a/react-phoenix/web/controllers/plugs/require_auth.ex b/react-phoenix/web/controllers/plugs/require_auth.ex
new file mode 100644
index 0000000..4462dbc
--- /dev/null
+++ b/react-phoenix/web/controllers/plugs/require_auth.ex
@@ -0,0 +1,20 @@
+defmodule Reddit.Plugs.RequireAuth do
+ import Phoenix.Controller, only: [put_flash: 3, redirect: 2]
+ import Plug.Conn
+
+ alias Reddit.Router.Helpers
+
+ def init(_params) do
+ end
+
+ def call(conn, _params) do
+ if conn.assigns.user do
+ conn
+ else
+ conn
+ |> put_flash(:error, "You must be logged in to do that")
+ |> redirect(to: Helpers.post_path(conn, :index))
+ |> halt()
+ end
+ end
+end
diff --git a/react-phoenix/web/controllers/plugs/set_user.ex b/react-phoenix/web/controllers/plugs/set_user.ex
new file mode 100644
index 0000000..a5e5a53
--- /dev/null
+++ b/react-phoenix/web/controllers/plugs/set_user.ex
@@ -0,0 +1,24 @@
+defmodule Reddit.Plugs.SetUser do
+ import Plug.Conn
+ import Phoenix.Controller
+
+ alias Reddit.Repo
+ alias Reddit.User
+ alias Elixgur.Router.Helpers
+
+ def init(_params) do
+ end
+
+ def call(conn, _params) do
+ user_id = get_session(conn, :user_id)
+
+ cond do
+ conn.assigns[:user] ->
+ conn
+ user = user_id && Repo.get(User, user_id) ->
+ assign(conn, :user, user)
+ true ->
+ assign(conn, :user, nil)
+ end
+ end
+end
diff --git a/react-phoenix/web/controllers/post_controller.ex b/react-phoenix/web/controllers/post_controller.ex
new file mode 100644
index 0000000..4ed30a6
--- /dev/null
+++ b/react-phoenix/web/controllers/post_controller.ex
@@ -0,0 +1,80 @@
+defmodule Reddit.PostController do
+ use Reddit.Web, :controller
+ alias Reddit.{Post}
+
+ plug Reddit.Plugs.RequireAuth when action in [:new, :create]
+ plug :check_post_owner when action in [:update, :edit, :delete]
+
+ def index(conn, _params) do
+ posts = Repo.all(Post)
+ render conn, "index.html", posts: posts
+ end
+
+ def show(conn, %{"id" => post_id}) do
+ post = Repo.get!(Post, post_id)
+ render conn, "show.html", post: post
+ end
+
+ def new(conn, _params) do
+ changeset = %Post{} |> Post.changeset(%{})
+
+ render conn, "new.html", changeset: changeset
+ end
+
+ def create(conn, %{"post" => post}) do
+ changeset = conn.assigns.user
+ |> build_assoc(:posts)
+ |> Post.changeset(post)
+
+ case Repo.insert(changeset) do
+ {:ok, post} ->
+ conn
+ |> put_flash(:info, "Post Created")
+ |> redirect(to: post_path(conn, :show, post))
+ {:error, changeset} ->
+ render(conn, "new.html", changeset: changeset)
+ end
+ end
+
+ def edit(conn, %{"id" => post_id}) do
+ post = Repo.get(Post, post_id)
+ changeset = post |> Post.changeset
+
+ render conn, "edit.html", post: post, changeset: changeset
+ end
+
+ def update(conn, %{"post" => post, "id" => post_id}) do
+ changeset = Repo.get(Post, post_id) |> Post.changeset(post)
+
+ case Repo.update(changeset) do
+ {:ok, post} ->
+ conn
+ |> put_flash(:info, "Post Updated")
+ |> redirect(to: post_path(conn, :show, post))
+ {:error, changeset} ->
+ render conn, "edit.html", changeset: changeset
+ end
+ end
+
+ def delete(conn, %{"id" => post_id}) do
+ Repo.get!(Post, post_id) |> Repo.delete!
+
+ conn
+ |> put_flash(:info, "Post Deleted")
+ |> redirect(to: post_path(conn, :index))
+ end
+
+ def check_post_owner(conn, _params) do
+ %{params: %{"id" => post_id}} = conn
+
+ case Repo.get(Post, post_id).user_id == conn.assigns.user.id do
+ true ->
+ conn
+ false ->
+ conn
+ |> put_flash(:error, "You cannot edit that")
+ |> redirect(to: post_path(conn, :index))
+ |> halt()
+ end
+ end
+end
diff --git a/react-phoenix/web/controllers/session_controller.ex b/react-phoenix/web/controllers/session_controller.ex
new file mode 100644
index 0000000..9c4a215
--- /dev/null
+++ b/react-phoenix/web/controllers/session_controller.ex
@@ -0,0 +1,48 @@
+defmodule Reddit.SessionController do
+ use Reddit.Web, :controller
+ plug Ueberauth
+
+ alias Reddit.User
+
+ def callback(%{assigns: %{ ueberauth_failure: failure }}= conn, _params) do
+ IO.inspect(failure)
+
+ conn
+ |> redirect(post_path(conn, :index))
+ end
+
+ def callback(%{assigns: %{ ueberauth_auth: auth }} = conn, %{"provider" => "github"}) do
+ changeset = User.changeset(%User{}, User.attrs_from_github(auth))
+
+ signin(conn, changeset)
+ end
+
+ def signout(conn, _params) do
+ conn
+ |> configure_session(drop: true)
+ |> redirect(to: post_path(conn, :index))
+ end
+
+ defp signin(conn, changeset) do
+ case insert_or_update_user(changeset) do
+ {:ok, user} ->
+ conn
+ |> put_flash(:info, "Welcome back")
+ |> put_session(:user_id, user.id)
+ |> redirect(to: post_path(conn, :index))
+ {:error, _reason} ->
+ conn
+ |> put_flash("Error signing in", :error)
+ |> redirect(to: post_path(conn, :index))
+ end
+ end
+
+ defp insert_or_update_user(changeset) do
+ case Repo.get_by(User, email: changeset.changes.email) do
+ nil ->
+ Repo.insert(changeset)
+ user ->
+ {:ok, user}
+ end
+ end
+end
diff --git a/react-phoenix/web/gettext.ex b/react-phoenix/web/gettext.ex
new file mode 100644
index 0000000..3d3a170
--- /dev/null
+++ b/react-phoenix/web/gettext.ex
@@ -0,0 +1,24 @@
+defmodule Reddit.Gettext do
+ @moduledoc """
+ A module providing Internationalization with a gettext-based API.
+
+ By using [Gettext](https://hexdocs.pm/gettext),
+ your module gains a set of macros for translations, for example:
+
+ import Reddit.Gettext
+
+ # Simple translation
+ gettext "Here is the string to translate"
+
+ # Plural translation
+ ngettext "Here is the string to translate",
+ "Here are the strings to translate",
+ 3
+
+ # Domain-based translation
+ dgettext "errors", "Here is the error message to translate"
+
+ See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
+ """
+ use Gettext, otp_app: :reddit
+end
diff --git a/react-phoenix/web/models/comment.ex b/react-phoenix/web/models/comment.ex
new file mode 100644
index 0000000..04ca0b3
--- /dev/null
+++ b/react-phoenix/web/models/comment.ex
@@ -0,0 +1,16 @@
+defmodule Reddit.Comment do
+ use Reddit.Web, :model
+
+ schema "comments" do
+ field :content, :string
+ belongs_to :user, Reddit.User
+ belongs_to :post, Reddit.Post
+
+ timestamps()
+ end
+
+ def changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:content])
+ end
+end
diff --git a/react-phoenix/web/models/post.ex b/react-phoenix/web/models/post.ex
new file mode 100644
index 0000000..7e1a100
--- /dev/null
+++ b/react-phoenix/web/models/post.ex
@@ -0,0 +1,17 @@
+defmodule Reddit.Post do
+ use Reddit.Web, :model
+
+ schema "posts" do
+ field :title, :string
+ belongs_to :user, Reddit.User
+ has_many :comments, Reddit.Comment
+
+ timestamps()
+ end
+
+ def changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:title])
+ |> validate_required([:title])
+ end
+end
diff --git a/react-phoenix/web/models/user.ex b/react-phoenix/web/models/user.ex
new file mode 100644
index 0000000..e674b4f
--- /dev/null
+++ b/react-phoenix/web/models/user.ex
@@ -0,0 +1,25 @@
+defmodule Reddit.User do
+ use Reddit.Web, :model
+
+ schema "users" do
+ field :email, :string
+ field :provider, :string
+ field :token, :string
+ has_many :posts, Reddit.Post
+
+ timestamps()
+ end
+
+ def attrs_from_github(auth) do
+ %{email: auth.info.email, token: auth.credentials.token, provider: "github"}
+ end
+
+ @doc """
+ Builds a changeset based on the `struct` and `params`.
+ """
+ def changeset(struct, params \\ %{}) do
+ struct
+ |> cast(params, [:email, :provider, :token])
+ |> validate_required([:email, :provider, :token])
+ end
+end
diff --git a/react-phoenix/web/router.ex b/react-phoenix/web/router.ex
new file mode 100644
index 0000000..b8b0471
--- /dev/null
+++ b/react-phoenix/web/router.ex
@@ -0,0 +1,35 @@
+defmodule Reddit.Router do
+ use Reddit.Web, :router
+
+ pipeline :browser do
+ plug :accepts, ["html"]
+ plug :fetch_session
+ plug :fetch_flash
+ plug :protect_from_forgery
+ plug :put_secure_browser_headers
+ plug Reddit.Plugs.SetUser
+ end
+
+ pipeline :api do
+ plug :accepts, ["json"]
+ end
+
+ scope "/", Reddit do
+ pipe_through :browser # Use the default browser stack
+
+ resources "/", PostController
+ end
+
+ scope "/auth", Reddit do
+ pipe_through :browser
+
+ get "/signout", SessionController, :signout
+ get "/:provider", SessionController, :request
+ get "/:provider/callback", SessionController, :callback
+ end
+
+ # Other scopes may use custom stacks.
+ # scope "/api", Reddit do
+ # pipe_through :api
+ # end
+end
diff --git a/react-phoenix/web/static/assets/favicon.ico b/react-phoenix/web/static/assets/favicon.ico
new file mode 100644
index 0000000..73de524
Binary files /dev/null and b/react-phoenix/web/static/assets/favicon.ico differ
diff --git a/react-phoenix/web/static/assets/images/phoenix.png b/react-phoenix/web/static/assets/images/phoenix.png
new file mode 100644
index 0000000..9c81075
Binary files /dev/null and b/react-phoenix/web/static/assets/images/phoenix.png differ
diff --git a/react-phoenix/web/static/assets/robots.txt b/react-phoenix/web/static/assets/robots.txt
new file mode 100644
index 0000000..3c9c7c0
--- /dev/null
+++ b/react-phoenix/web/static/assets/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/react-phoenix/web/static/css/app.css b/react-phoenix/web/static/css/app.css
new file mode 100644
index 0000000..94ce6d2
--- /dev/null
+++ b/react-phoenix/web/static/css/app.css
@@ -0,0 +1,38 @@
+/* This file is for your main application css. */
+
+.has-error {
+ color: red;
+ position: absolute;
+ right: 0px;
+ top: 18px;
+}
+
+.right {
+ display: flex;
+}
+
+.right a {
+ margin-right: 10px;
+}
+
+.notification {
+ position: absolute !important;
+ height: 50px;
+ width: 100px;
+ bottom: 20px;
+ left: 20px;
+ text-align: center;
+}
+
+
+.help-block {
+ color: red;
+ text-transform: capitalize;
+ position: absolute;
+ top: 35px;
+}
+
+.form-group {
+ position: relative;
+ margin-bottom: 25px;
+}
diff --git a/react-phoenix/web/static/js/CommentBox.js b/react-phoenix/web/static/js/CommentBox.js
new file mode 100644
index 0000000..5f7e93c
--- /dev/null
+++ b/react-phoenix/web/static/js/CommentBox.js
@@ -0,0 +1,30 @@
+import React, { Component } from 'react';
+
+class CommentBox extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = { text: '' };
+ }
+
+ onSubmit(event) {
+ event.preventDefault();
+
+ this.props.onCommentCreate(this.state.text);
+ this.setState({ text: '' });
+ }
+
+ render() {
+ return (
+
+ );
+ }
+}
+
+export default CommentBox;
diff --git a/react-phoenix/web/static/js/CommentsList.js b/react-phoenix/web/static/js/CommentsList.js
new file mode 100644
index 0000000..b7e1bfb
--- /dev/null
+++ b/react-phoenix/web/static/js/CommentsList.js
@@ -0,0 +1,19 @@
+import React, { Component } from 'react';
+
+class CommentsList extends Component {
+ renderComments() {
+ return this.props.comments.map(comment =>
+ {comment.content}
+ );
+ }
+
+ render() {
+ return (
+
+ {this.renderComments()}
+
+ );
+ }
+};
+
+export default CommentsList;
diff --git a/react-phoenix/web/static/js/app.js b/react-phoenix/web/static/js/app.js
new file mode 100644
index 0000000..f94bc41
--- /dev/null
+++ b/react-phoenix/web/static/js/app.js
@@ -0,0 +1,46 @@
+import React, { Component } from 'react';
+import ReactDOM from 'react-dom';
+import "phoenix_html"
+import { Socket } from 'phoenix';
+import CommentsList from './CommentsList';
+import CommentBox from './CommentBox';
+
+class App extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = { comments: [] };
+ }
+
+ componentWillMount() {
+ const socket = new Socket('/socket', {params: {auth_token: window.redditToken}})
+ socket.connect()
+
+ this.channel = socket.channel(`comments:${this.props.postId}`, {})
+ this.channel.join()
+ .receive('ok', resp => { this.setState({comments: resp.comments}); })
+ .receive('error', resp => { console.log('Unable to join', resp) })
+
+ this.channel.on(`comments:${this.props.postId}:new`, (data) => {
+ const newComments = data.comments;
+ this.setState({ comments: [...this.state.comments, ...newComments] });
+ });
+ }
+
+ onCommentCreate(text) {
+ this.channel.push('comment:add', { content: text });
+ }
+
+ render() {
+ return (
+
+
+
+
+ );
+ }
+}
+
+window.renderCommentsApp = (target, postId) => {
+ ReactDOM.render( , document.getElementById(target));
+};
diff --git a/react-phoenix/web/static/js/socket.js b/react-phoenix/web/static/js/socket.js
new file mode 100644
index 0000000..e69de29
diff --git a/react-phoenix/web/templates/layout/_flash.html.eex b/react-phoenix/web/templates/layout/_flash.html.eex
new file mode 100644
index 0000000..6813b4b
--- /dev/null
+++ b/react-phoenix/web/templates/layout/_flash.html.eex
@@ -0,0 +1,13 @@
+
+ <%= if get_flash(@conn, :info) do %>
+
+ <%= get_flash(@conn, :info) %>
+
+ <% end %>
+
+ <%= if get_flash(@conn, :error) do %>
+
+ <%= get_flash(@conn, :error) %>
+
+ <% end %>
+
diff --git a/react-phoenix/web/templates/layout/app.html.eex b/react-phoenix/web/templates/layout/app.html.eex
new file mode 100644
index 0000000..6761c5d
--- /dev/null
+++ b/react-phoenix/web/templates/layout/app.html.eex
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+ Hello Reddit!
+ ">
+
+
+
+
+
+
+
+
+
+
Logo
+
+ <%= if @conn.assigns[:user] do %>
+
+ <%= link "Logout", to: session_path(@conn, :signout) %>
+
+ <% else %>
+
+ <%= link "Sign in with Github", to: session_path(@conn, :request, "github") %>
+
+ <% end %>
+
+
+
+
+ <%= render "_flash.html", conn: @conn %>
+
+
+
+ <%= render @view_module, @view_template, assigns %>
+
+
+
+
+
+
diff --git a/react-phoenix/web/templates/post/edit.html.eex b/react-phoenix/web/templates/post/edit.html.eex
new file mode 100644
index 0000000..b5be39f
--- /dev/null
+++ b/react-phoenix/web/templates/post/edit.html.eex
@@ -0,0 +1,8 @@
+<%= form_for @changeset, post_path(@conn, :update, @post), fn f -> %>
+
+ <%= text_input f, :title, placeholder: "Title", class: "form-control" %>
+ <%= error_tag f, :title %>
+
+
+ <%= submit "Save Post", class: "btn btn-primary" %>
+<%= end %>
diff --git a/react-phoenix/web/templates/post/index.html.eex b/react-phoenix/web/templates/post/index.html.eex
new file mode 100644
index 0000000..d17ce1d
--- /dev/null
+++ b/react-phoenix/web/templates/post/index.html.eex
@@ -0,0 +1,21 @@
+Posts
+
+
+ <%= for post <- @posts do %>
+
+ <%= link post.title, to: post_path(@conn, :show, post) %>
+ <%= if @conn.assigns.user.id == post.user_id do %>
+
+ <%= link "Delete", to: post_path(@conn, :delete, post), method: :delete %>
+ <%= link "Edit", to: post_path(@conn, :edit, post) %>
+
+ <% end %>
+
+ <% end %>
+
+
+
+ <%= link to: post_path(@conn, :new), class: "btn-floating btn-large waves-effect waves-light red" do %>
+ add
+ <% end %>
+
diff --git a/react-phoenix/web/templates/post/new.html.eex b/react-phoenix/web/templates/post/new.html.eex
new file mode 100644
index 0000000..d40746f
--- /dev/null
+++ b/react-phoenix/web/templates/post/new.html.eex
@@ -0,0 +1,8 @@
+<%= form_for @changeset, post_path(@conn, :create), fn f -> %>
+
+ <%= text_input f, :title, placeholder: "Title", class: "form-control" %>
+ <%= error_tag f, :title %>
+
+
+ <%= submit "Create Post", class: "btn btn-primary" %>
+<%= end %>
diff --git a/react-phoenix/web/templates/post/show.html.eex b/react-phoenix/web/templates/post/show.html.eex
new file mode 100644
index 0000000..1d5ebf1
--- /dev/null
+++ b/react-phoenix/web/templates/post/show.html.eex
@@ -0,0 +1,8 @@
+<%= @post.title %>
+
+
+
diff --git a/react-phoenix/web/views/comment_view.ex b/react-phoenix/web/views/comment_view.ex
new file mode 100644
index 0000000..62d5a09
--- /dev/null
+++ b/react-phoenix/web/views/comment_view.ex
@@ -0,0 +1,10 @@
+defmodule Reddit.CommentView do
+ use Reddit.Web, :view
+
+ def render("comments.json", %{comment: comment}) do
+ %{
+ id: comment.id,
+ content: comment.content
+ }
+ end
+end
diff --git a/react-phoenix/web/views/error_helpers.ex b/react-phoenix/web/views/error_helpers.ex
new file mode 100644
index 0000000..998388f
--- /dev/null
+++ b/react-phoenix/web/views/error_helpers.ex
@@ -0,0 +1,40 @@
+defmodule Reddit.ErrorHelpers do
+ @moduledoc """
+ Conveniences for translating and building error messages.
+ """
+
+ use Phoenix.HTML
+
+ @doc """
+ Generates tag for inlined form input errors.
+ """
+ def error_tag(form, field) do
+ if error = form.errors[field] do
+ content_tag :span, translate_error(error), class: "help-block"
+ end
+ end
+
+ @doc """
+ Translates an error message using gettext.
+ """
+ def translate_error({msg, opts}) do
+ # Because error messages were defined within Ecto, we must
+ # call the Gettext module passing our Gettext backend. We
+ # also use the "errors" domain as translations are placed
+ # in the errors.po file.
+ # Ecto will pass the :count keyword if the error message is
+ # meant to be pluralized.
+ # On your own code and templates, depending on whether you
+ # need the message to be pluralized or not, this could be
+ # written simply as:
+ #
+ # dngettext "errors", "1 file", "%{count} files", count
+ # dgettext "errors", "is invalid"
+ #
+ if count = opts[:count] do
+ Gettext.dngettext(Reddit.Gettext, "errors", msg, msg, count, opts)
+ else
+ Gettext.dgettext(Reddit.Gettext, "errors", msg, opts)
+ end
+ end
+end
diff --git a/react-phoenix/web/views/error_view.ex b/react-phoenix/web/views/error_view.ex
new file mode 100644
index 0000000..8ea67ef
--- /dev/null
+++ b/react-phoenix/web/views/error_view.ex
@@ -0,0 +1,17 @@
+defmodule Reddit.ErrorView do
+ use Reddit.Web, :view
+
+ def render("404.html", _assigns) do
+ "Page not found"
+ end
+
+ def render("500.html", _assigns) do
+ "Internal server error"
+ end
+
+ # In case no render clause matches or no
+ # template is found, let's render it as 500
+ def template_not_found(_template, assigns) do
+ render "500.html", assigns
+ end
+end
diff --git a/react-phoenix/web/views/layout_view.ex b/react-phoenix/web/views/layout_view.ex
new file mode 100644
index 0000000..37a326b
--- /dev/null
+++ b/react-phoenix/web/views/layout_view.ex
@@ -0,0 +1,3 @@
+defmodule Reddit.LayoutView do
+ use Reddit.Web, :view
+end
diff --git a/react-phoenix/web/views/post_view.ex b/react-phoenix/web/views/post_view.ex
new file mode 100644
index 0000000..614fa47
--- /dev/null
+++ b/react-phoenix/web/views/post_view.ex
@@ -0,0 +1,3 @@
+defmodule Reddit.PostView do
+ use Reddit.Web, :view
+end
diff --git a/react-phoenix/web/web.ex b/react-phoenix/web/web.ex
new file mode 100644
index 0000000..7e2f511
--- /dev/null
+++ b/react-phoenix/web/web.ex
@@ -0,0 +1,82 @@
+defmodule Reddit.Web do
+ @moduledoc """
+ A module that keeps using definitions for controllers,
+ views and so on.
+
+ This can be used in your application as:
+
+ use Reddit.Web, :controller
+ use Reddit.Web, :view
+
+ The definitions below will be executed for every view,
+ controller, etc, so keep them short and clean, focused
+ on imports, uses and aliases.
+
+ Do NOT define functions inside the quoted expressions
+ below.
+ """
+
+ def model do
+ quote do
+ use Ecto.Schema
+
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+ end
+ end
+
+ def controller do
+ quote do
+ use Phoenix.Controller
+
+ alias Reddit.Repo
+ import Ecto
+ import Ecto.Query
+
+ import Reddit.Router.Helpers
+ import Reddit.Gettext
+ import Reddit.Queries
+ end
+ end
+
+ def view do
+ quote do
+ use Phoenix.View, root: "web/templates"
+
+ # Import convenience functions from controllers
+ import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
+
+ # Use all HTML functionality (forms, tags, etc)
+ use Phoenix.HTML
+
+ import Reddit.Router.Helpers
+ import Reddit.ErrorHelpers
+ import Reddit.Gettext
+ end
+ end
+
+ def router do
+ quote do
+ use Phoenix.Router
+ end
+ end
+
+ def channel do
+ quote do
+ use Phoenix.Channel
+
+ alias Reddit.Repo
+ import Ecto
+ import Ecto.Query
+ import Reddit.Gettext
+ end
+ end
+
+ @doc """
+ When used, dispatch to the appropriate controller/view/etc.
+ """
+ defmacro __using__(which) when is_atom(which) do
+ apply(__MODULE__, which, [])
+ end
+end
diff --git a/update/.gitignore b/update/.gitignore
new file mode 100644
index 0000000..d5be28f
--- /dev/null
+++ b/update/.gitignore
@@ -0,0 +1,27 @@
+# App artifacts
+/_build
+/db
+/deps
+/*.ez
+
+# Generated on crash by the VM
+erl_crash.dump
+
+# Generated on crash by NPM
+npm-debug.log
+
+# Static artifacts
+/assets/node_modules
+
+# Since we are building assets from assets/,
+# we ignore priv/static. You may want to comment
+# this depending on your deployment strategy.
+/priv/static/
+
+# Files matching config/*.secret.exs pattern contain sensitive
+# data and you should not commit them into version control.
+#
+# Alternatively, you may comment the line below and commit the
+# secrets files as long as you replace their contents by environment
+# variables.
+/config/*.secret.exs
\ No newline at end of file
diff --git a/update/README.md b/update/README.md
new file mode 100644
index 0000000..2b80f3a
--- /dev/null
+++ b/update/README.md
@@ -0,0 +1,20 @@
+# Update
+
+To start your Phoenix server:
+
+ * Install dependencies with `mix deps.get`
+ * Create and migrate your database with `mix ecto.create && mix ecto.migrate`
+ * Install Node.js dependencies with `cd assets && npm install`
+ * Start Phoenix endpoint with `mix phx.server`
+
+Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
+
+Ready to run in production? Please [check our deployment guides](http://www.phoenixframework.org/docs/deployment).
+
+## Learn more
+
+ * Official website: http://www.phoenixframework.org/
+ * Guides: http://phoenixframework.org/docs/overview
+ * Docs: https://hexdocs.pm/phoenix
+ * Mailing list: http://groups.google.com/group/phoenix-talk
+ * Source: https://github.com/phoenixframework/phoenix
diff --git a/update/assets/brunch-config.js b/update/assets/brunch-config.js
new file mode 100644
index 0000000..b15df46
--- /dev/null
+++ b/update/assets/brunch-config.js
@@ -0,0 +1,62 @@
+exports.config = {
+ // See http://brunch.io/#documentation for docs.
+ files: {
+ javascripts: {
+ joinTo: "js/app.js"
+
+ // To use a separate vendor.js bundle, specify two files path
+ // http://brunch.io/docs/config#-files-
+ // joinTo: {
+ // "js/app.js": /^js/,
+ // "js/vendor.js": /^(?!js)/
+ // }
+ //
+ // To change the order of concatenation of files, explicitly mention here
+ // order: {
+ // before: [
+ // "vendor/js/jquery-2.1.1.js",
+ // "vendor/js/bootstrap.min.js"
+ // ]
+ // }
+ },
+ stylesheets: {
+ joinTo: "css/app.css"
+ },
+ templates: {
+ joinTo: "js/app.js"
+ }
+ },
+
+ conventions: {
+ // This option sets where we should place non-css and non-js assets in.
+ // By default, we set this to "/assets/static". Files in this directory
+ // will be copied to `paths.public`, which is "priv/static" by default.
+ assets: /^(static)/
+ },
+
+ // Phoenix paths configuration
+ paths: {
+ // Dependencies and current project directories to watch
+ watched: ["static", "css", "js", "vendor"],
+ // Where to compile files to
+ public: "../priv/static"
+ },
+
+ // Configure your plugins
+ plugins: {
+ babel: {
+ // Do not use ES6 compiler in vendor code
+ ignore: [/vendor/]
+ }
+ },
+
+ modules: {
+ autoRequire: {
+ "js/app.js": ["js/app"]
+ }
+ },
+
+ npm: {
+ enabled: true
+ }
+};
diff --git a/update/assets/css/app.css b/update/assets/css/app.css
new file mode 100644
index 0000000..5314c34
--- /dev/null
+++ b/update/assets/css/app.css
@@ -0,0 +1 @@
+/* This file is for your main application css. */
\ No newline at end of file
diff --git a/update/assets/css/phoenix.css b/update/assets/css/phoenix.css
new file mode 100644
index 0000000..0b406d7
--- /dev/null
+++ b/update/assets/css/phoenix.css
@@ -0,0 +1,77 @@
+/* Includes Bootstrap as well as some default style for the starter
+ * application. This can be safely deleted to start fresh.
+ */
+
+/*!
+ * Bootstrap v3.3.5 (http://getbootstrap.com)
+ * Copyright 2011-2015 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ *//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:2em}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{height:0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{margin:0;font:inherit;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid silver}legend{padding:0;border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="javascript:"]:after,a[href^="#"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff2) format('woff2'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\00a5"}.glyphicon-jpy:before{content:"\00a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:after,:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:focus,a.text-primary:hover{color:#286090}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:focus,a.bg-primary:hover{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;margin-left:-5px;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eee;border-left:0}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:''}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:'\00A0 \2014'}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-10,.col-xs-11,.col-xs-12,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=checkbox]:focus,input[type=radio]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm{line-height:30px}.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-top:4px\9;margin-left:-20px}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.checkbox-inline.disabled,.radio-inline.disabled,fieldset[disabled] .checkbox-inline,fieldset[disabled] .radio-inline{cursor:not-allowed}.checkbox.disabled label,.radio.disabled label,fieldset[disabled] .checkbox label,fieldset[disabled] .radio label{cursor:not-allowed}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.checkbox label,.has-success.checkbox-inline label,.has-success.radio label,.has-success.radio-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.checkbox label,.has-warning.checkbox-inline label,.has-warning.radio label,.has-warning.radio-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.checkbox label,.has-error.checkbox-inline label,.has-error.radio label,.has-error.radio-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .checkbox,.form-horizontal .radio{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:14.33px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-image:none;border:1px solid transparent;border-radius:4px}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#333;text-decoration:none}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;opacity:.65}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.dropdown-toggle.btn-default.focus,.open>.dropdown-toggle.btn-default:focus,.open>.dropdown-toggle.btn-default:hover{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.dropdown-toggle.btn-primary.focus,.open>.dropdown-toggle.btn-primary:focus,.open>.dropdown-toggle.btn-primary:hover{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.active,.btn-primary:active,.open>.dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;border-color:#398439}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.dropdown-toggle.btn-success.focus,.open>.dropdown-toggle.btn-success:focus,.open>.dropdown-toggle.btn-success:hover{color:#fff;background-color:#398439;border-color:#255625}.btn-success.active,.btn-success:active,.open>.dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.dropdown-toggle.btn-info.focus,.open>.dropdown-toggle.btn-info:focus,.open>.dropdown-toggle.btn-info:hover{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.active,.btn-info:active,.open>.dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.dropdown-toggle.btn-warning.focus,.open>.dropdown-toggle.btn-warning:focus,.open>.dropdown-toggle.btn-warning:hover{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.active,.btn-warning:active,.open>.dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.dropdown-toggle.btn-danger.focus,.open>.dropdown-toggle.btn-danger:focus,.open>.dropdown-toggle.btn-danger:hover{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.active,.btn-danger:active,.open>.dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-left-radius:0;border-top-right-radius:0;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn,textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn,textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group .form-control,.input-group-addon,.input-group-btn{display:table-cell}.input-group .form-control:not(:first-child):not(:last-child),.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;-webkit-overflow-scrolling:touch;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;height:50px;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-left-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{color:#555;background-color:#e7e7e7}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{color:#fff;background-color:#080808}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:3;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:2;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:focus,.label-success[href]:hover{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:focus,.label-info[href]:hover{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail a>img,.thumbnail>img{margin-right:auto;margin-left:auto}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table caption,.panel>.table-responsive>.table caption{padding-right:15px;padding-left:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0}.modal-open{overflow:hidden}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out;-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translate(0,-25%)}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0,0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{min-height:16.43px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:12px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;filter:alpha(opacity=0);opacity:0;line-break:auto}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,.25);border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,.25);border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25)}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>a>img,.carousel-inner>.item>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{left:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{left:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{left:0;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);background-repeat:repeat-x}.carousel-control:focus,.carousel-control:hover{color:#fff;text-decoration:none;filter:alpha(opacity=90);outline:0;opacity:.9}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000\9;background-color:rgba(0,0,0,0);border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-15px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-15px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-15px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before,.btn-toolbar:after,.btn-toolbar:before,.clearfix:after,.clearfix:before,.container-fluid:after,.container-fluid:before,.container:after,.container:before,.dl-horizontal dd:after,.dl-horizontal dd:before,.form-horizontal .form-group:after,.form-horizontal .form-group:before,.modal-footer:after,.modal-footer:before,.nav:after,.nav:before,.navbar-collapse:after,.navbar-collapse:before,.navbar-header:after,.navbar-header:before,.navbar:after,.navbar:before,.pager:after,.pager:before,.panel-body:after,.panel-body:before,.row:after,.row:before{display:table;content:" "}.btn-group-vertical>.btn-group:after,.btn-toolbar:after,.clearfix:after,.container-fluid:after,.container:after,.dl-horizontal dd:after,.form-horizontal .form-group:after,.modal-footer:after,.nav:after,.navbar-collapse:after,.navbar-header:after,.navbar:after,.pager:after,.panel-body:after,.row:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-md,.visible-sm,.visible-xs{display:none!important}.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}
+
+/* Space out content a bit */
+body, form, ul, table {
+ margin-top: 20px;
+ margin-bottom: 20px;
+}
+
+/* Phoenix flash messages */
+.alert:empty { display: none; }
+
+/* Custom page header */
+.header {
+ border-bottom: 1px solid #e5e5e5;
+}
+.logo {
+ width: 519px;
+ height: 71px;
+ display: inline-block;
+ margin-bottom: 1em;
+ background-image: url("/images/phoenix.png");
+ background-size: 519px 71px;
+}
+
+/* Everything but the jumbotron gets side spacing for mobile first views */
+.header,
+.marketing {
+ padding-right: 15px;
+ padding-left: 15px;
+}
+
+/* Customize container */
+@media (min-width: 768px) {
+ .container {
+ max-width: 730px;
+ }
+}
+.container-narrow > hr {
+ margin: 30px 0;
+}
+
+/* Main marketing message */
+.jumbotron {
+ text-align: center;
+ border-bottom: 1px solid #e5e5e5;
+}
+
+/* Supporting marketing content */
+.marketing {
+ margin: 35px 0;
+}
+
+/* Responsive: Portrait tablets and up */
+@media screen and (min-width: 768px) {
+ /* Remove the padding we set earlier */
+ .header,
+ .marketing {
+ padding-right: 0;
+ padding-left: 0;
+ }
+ /* Space out the masthead */
+ .header {
+ margin-bottom: 30px;
+ }
+ /* Remove the bottom border on the jumbotron for visual effect */
+ .jumbotron {
+ border-bottom: 0;
+ }
+}
\ No newline at end of file
diff --git a/update/assets/js/app.js b/update/assets/js/app.js
new file mode 100644
index 0000000..e7549b9
--- /dev/null
+++ b/update/assets/js/app.js
@@ -0,0 +1,21 @@
+// Brunch automatically concatenates all files in your
+// watched paths. Those paths can be configured at
+// config.paths.watched in "brunch-config.js".
+//
+// However, those files will only be executed if
+// explicitly imported. The only exception are files
+// in vendor, which are never wrapped in imports and
+// therefore are always executed.
+
+// Import dependencies
+//
+// If you no longer want to use a dependency, remember
+// to also remove its path from "config.paths.watched".
+import "phoenix_html"
+
+// Import local files
+//
+// Local files can be imported directly using relative
+// paths "./socket" or full ones "web/static/js/socket".
+
+// import socket from "./socket"
diff --git a/update/assets/js/socket.js b/update/assets/js/socket.js
new file mode 100644
index 0000000..5c23a67
--- /dev/null
+++ b/update/assets/js/socket.js
@@ -0,0 +1,62 @@
+// NOTE: The contents of this file will only be executed if
+// you uncomment its entry in "assets/js/app.js".
+
+// To use Phoenix channels, the first step is to import Socket
+// and connect at the socket path in "lib/web/endpoint.ex":
+import {Socket} from "phoenix"
+
+let socket = new Socket("/socket", {params: {token: window.userToken}})
+
+// When you connect, you'll often need to authenticate the client.
+// For example, imagine you have an authentication plug, `MyAuth`,
+// which authenticates the session and assigns a `:current_user`.
+// If the current user exists you can assign the user's token in
+// the connection for use in the layout.
+//
+// In your "lib/web/router.ex":
+//
+// pipeline :browser do
+// ...
+// plug MyAuth
+// plug :put_user_token
+// end
+//
+// defp put_user_token(conn, _) do
+// if current_user = conn.assigns[:current_user] do
+// token = Phoenix.Token.sign(conn, "user socket", current_user.id)
+// assign(conn, :user_token, token)
+// else
+// conn
+// end
+// end
+//
+// Now you need to pass this token to JavaScript. You can do so
+// inside a script tag in "lib/web/templates/layout/app.html.eex":
+//
+//
+//
+// You will need to verify the user token in the "connect/2" function
+// in "lib/web/channels/user_socket.ex":
+//
+// def connect(%{"token" => token}, socket) do
+// # max_age: 1209600 is equivalent to two weeks in seconds
+// case Phoenix.Token.verify(socket, "user socket", token, max_age: 1209600) do
+// {:ok, user_id} ->
+// {:ok, assign(socket, :user, user_id)}
+// {:error, reason} ->
+// :error
+// end
+// end
+//
+// Finally, pass the token on connect as below. Or remove it
+// from connect if you don't care about authentication.
+
+socket.connect()
+
+// Now that you are connected, you can join channels with a topic:
+let channel = socket.channel("topic:subtopic", {})
+channel.join()
+ .receive("ok", resp => { console.log("Joined successfully", resp) })
+ .receive("error", resp => { console.log("Unable to join", resp) })
+
+export default socket
diff --git a/update/assets/package.json b/update/assets/package.json
new file mode 100644
index 0000000..4cc3986
--- /dev/null
+++ b/update/assets/package.json
@@ -0,0 +1,18 @@
+{
+ "repository": {},
+ "license": "MIT",
+ "scripts": {
+ "deploy": "brunch build --production",
+ "watch": "brunch watch --stdin"
+ },
+ "dependencies": {
+ "phoenix": "file:../deps/phoenix",
+ "phoenix_html": "file:../deps/phoenix_html"
+ },
+ "devDependencies": {
+ "babel-brunch": "6.1.1",
+ "brunch": "2.10.9",
+ "clean-css-brunch": "2.10.0",
+ "uglify-js-brunch": "2.10.0"
+ }
+}
diff --git a/update/assets/static/favicon.ico b/update/assets/static/favicon.ico
new file mode 100644
index 0000000..73de524
Binary files /dev/null and b/update/assets/static/favicon.ico differ
diff --git a/update/assets/static/images/phoenix.png b/update/assets/static/images/phoenix.png
new file mode 100644
index 0000000..9c81075
Binary files /dev/null and b/update/assets/static/images/phoenix.png differ
diff --git a/update/assets/static/robots.txt b/update/assets/static/robots.txt
new file mode 100644
index 0000000..3c9c7c0
--- /dev/null
+++ b/update/assets/static/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/update/config/config.exs b/update/config/config.exs
new file mode 100644
index 0000000..9dff2f9
--- /dev/null
+++ b/update/config/config.exs
@@ -0,0 +1,27 @@
+# This file is responsible for configuring your application
+# and its dependencies with the aid of the Mix.Config module.
+#
+# This configuration file is loaded before any dependency and
+# is restricted to this project.
+use Mix.Config
+
+# General application configuration
+config :update,
+ ecto_repos: [Update.Repo]
+
+# Configures the endpoint
+config :update, UpdateWeb.Endpoint,
+ url: [host: "localhost"],
+ secret_key_base: "VAgvpUJWWIViThsi3S2z5bbfE8V9EAc8Cag7sJcjxHRkMQjzac19F5fWs/bciVt+",
+ render_errors: [view: UpdateWeb.ErrorView, accepts: ~w(html json)],
+ pubsub: [name: Update.PubSub,
+ adapter: Phoenix.PubSub.PG2]
+
+# Configures Elixir's Logger
+config :logger, :console,
+ format: "$time $metadata[$level] $message\n",
+ metadata: [:request_id]
+
+# Import environment specific config. This must remain at the bottom
+# of this file so it overrides the configuration defined above.
+import_config "#{Mix.env}.exs"
diff --git a/update/config/dev.exs b/update/config/dev.exs
new file mode 100644
index 0000000..dcf608c
--- /dev/null
+++ b/update/config/dev.exs
@@ -0,0 +1,58 @@
+use Mix.Config
+
+# For development, we disable any cache and enable
+# debugging and code reloading.
+#
+# The watchers configuration can be used to run external
+# watchers to your application. For example, we use it
+# with brunch.io to recompile .js and .css sources.
+config :update, UpdateWeb.Endpoint,
+ http: [port: 4000],
+ debug_errors: true,
+ code_reloader: true,
+ check_origin: false,
+ watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
+ cd: Path.expand("../assets", __DIR__)]]
+
+# ## SSL Support
+#
+# In order to use HTTPS in development, a self-signed
+# certificate can be generated by running the following
+# command from your terminal:
+#
+# openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" -keyout priv/server.key -out priv/server.pem
+#
+# The `http:` config above can be replaced with:
+#
+# https: [port: 4000, keyfile: "priv/server.key", certfile: "priv/server.pem"],
+#
+# If desired, both `http:` and `https:` keys can be
+# configured to run both http and https servers on
+# different ports.
+
+# Watch static and templates for browser reloading.
+config :update, UpdateWeb.Endpoint,
+ live_reload: [
+ patterns: [
+ ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
+ ~r{priv/gettext/.*(po)$},
+ ~r{lib/update_web/views/.*(ex)$},
+ ~r{lib/update_web/templates/.*(eex)$}
+ ]
+ ]
+
+# Do not include metadata nor timestamps in development logs
+config :logger, :console, format: "[$level] $message\n"
+
+# Set a higher stacktrace during development. Avoid configuring such
+# in production as building large stacktraces may be expensive.
+config :phoenix, :stacktrace_depth, 20
+
+# Configure your database
+config :update, Update.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "stephengrider",
+ password: "",
+ database: "update_dev",
+ hostname: "localhost",
+ pool_size: 10
diff --git a/update/config/prod.exs b/update/config/prod.exs
new file mode 100644
index 0000000..5acc065
--- /dev/null
+++ b/update/config/prod.exs
@@ -0,0 +1,64 @@
+use Mix.Config
+
+# For production, we often load configuration from external
+# sources, such as your system environment. For this reason,
+# you won't find the :http configuration below, but set inside
+# UpdateWeb.Endpoint.init/2 when load_from_system_env is
+# true. Any dynamic configuration should be done there.
+#
+# Don't forget to configure the url host to something meaningful,
+# Phoenix uses this information when generating URLs.
+#
+# Finally, we also include the path to a cache manifest
+# containing the digested version of static files. This
+# manifest is generated by the mix phx.digest task
+# which you typically run after static files are built.
+config :update, UpdateWeb.Endpoint,
+ load_from_system_env: true,
+ url: [host: "example.com", port: 80],
+ cache_static_manifest: "priv/static/cache_manifest.json"
+
+# Do not print debug messages in production
+config :logger, level: :info
+
+# ## SSL Support
+#
+# To get SSL working, you will need to add the `https` key
+# to the previous section and set your `:url` port to 443:
+#
+# config :update, UpdateWeb.Endpoint,
+# ...
+# url: [host: "example.com", port: 443],
+# https: [:inet6,
+# port: 443,
+# keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
+# certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
+#
+# Where those two env variables return an absolute path to
+# the key and cert in disk or a relative path inside priv,
+# for example "priv/ssl/server.key".
+#
+# We also recommend setting `force_ssl`, ensuring no data is
+# ever sent via http, always redirecting to https:
+#
+# config :update, UpdateWeb.Endpoint,
+# force_ssl: [hsts: true]
+#
+# Check `Plug.SSL` for all available options in `force_ssl`.
+
+# ## Using releases
+#
+# If you are doing OTP releases, you need to instruct Phoenix
+# to start the server for all endpoints:
+#
+# config :phoenix, :serve_endpoints, true
+#
+# Alternatively, you can configure exactly which server to
+# start per endpoint:
+#
+# config :update, UpdateWeb.Endpoint, server: true
+#
+
+# Finally import the config/prod.secret.exs
+# which should be versioned separately.
+import_config "prod.secret.exs"
diff --git a/update/config/test.exs b/update/config/test.exs
new file mode 100644
index 0000000..a26f161
--- /dev/null
+++ b/update/config/test.exs
@@ -0,0 +1,19 @@
+use Mix.Config
+
+# We don't run a server during test. If one is required,
+# you can enable the server option below.
+config :update, UpdateWeb.Endpoint,
+ http: [port: 4001],
+ server: false
+
+# Print only warnings and errors during test
+config :logger, level: :warn
+
+# Configure your database
+config :update, Update.Repo,
+ adapter: Ecto.Adapters.Postgres,
+ username: "postgres",
+ password: "postgres",
+ database: "update_test",
+ hostname: "localhost",
+ pool: Ecto.Adapters.SQL.Sandbox
diff --git a/update/lib/update.ex b/update/lib/update.ex
new file mode 100644
index 0000000..e07b486
--- /dev/null
+++ b/update/lib/update.ex
@@ -0,0 +1,9 @@
+defmodule Update do
+ @moduledoc """
+ Update keeps the contexts that define your domain
+ and business logic.
+
+ Contexts are also responsible for managing your data, regardless
+ if it comes from the database, an external API or others.
+ """
+end
diff --git a/update/lib/update/accounts/accounts.ex b/update/lib/update/accounts/accounts.ex
new file mode 100644
index 0000000..6acb4b6
--- /dev/null
+++ b/update/lib/update/accounts/accounts.ex
@@ -0,0 +1,104 @@
+defmodule Update.Accounts do
+ @moduledoc """
+ The Accounts context.
+ """
+
+ import Ecto.Query, warn: false
+ alias Update.Repo
+
+ alias Update.Accounts.User
+
+ @doc """
+ Returns the list of users.
+
+ ## Examples
+
+ iex> list_users()
+ [%User{}, ...]
+
+ """
+ def list_users do
+ Repo.all(User)
+ end
+
+ @doc """
+ Gets a single user.
+
+ Raises `Ecto.NoResultsError` if the User does not exist.
+
+ ## Examples
+
+ iex> get_user!(123)
+ %User{}
+
+ iex> get_user!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_user!(id), do: Repo.get!(User, id)
+
+ @doc """
+ Creates a user.
+
+ ## Examples
+
+ iex> create_user(%{field: value})
+ {:ok, %User{}}
+
+ iex> create_user(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_user(attrs \\ %{}) do
+ %User{}
+ |> User.changeset(attrs)
+ |> Repo.insert()
+ end
+
+ @doc """
+ Updates a user.
+
+ ## Examples
+
+ iex> update_user(user, %{field: new_value})
+ {:ok, %User{}}
+
+ iex> update_user(user, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_user(%User{} = user, attrs) do
+ user
+ |> User.changeset(attrs)
+ |> Repo.update()
+ end
+
+ @doc """
+ Deletes a User.
+
+ ## Examples
+
+ iex> delete_user(user)
+ {:ok, %User{}}
+
+ iex> delete_user(user)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_user(%User{} = user) do
+ Repo.delete(user)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking user changes.
+
+ ## Examples
+
+ iex> change_user(user)
+ %Ecto.Changeset{source: %User{}}
+
+ """
+ def change_user(%User{} = user) do
+ User.changeset(user, %{})
+ end
+end
diff --git a/update/lib/update/accounts/user.ex b/update/lib/update/accounts/user.ex
new file mode 100644
index 0000000..ee17d40
--- /dev/null
+++ b/update/lib/update/accounts/user.ex
@@ -0,0 +1,19 @@
+defmodule Update.Accounts.User do
+ use Ecto.Schema
+ import Ecto.Changeset
+ alias Update.Accounts.User
+
+
+ schema "users" do
+ field :email, :string
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(%User{} = user, attrs) do
+ user
+ |> cast(attrs, [:email])
+ |> validate_required([:email])
+ end
+end
diff --git a/update/lib/update/application.ex b/update/lib/update/application.ex
new file mode 100644
index 0000000..28b28b4
--- /dev/null
+++ b/update/lib/update/application.ex
@@ -0,0 +1,31 @@
+defmodule Update.Application do
+ use Application
+
+ # See https://hexdocs.pm/elixir/Application.html
+ # for more information on OTP Applications
+ def start(_type, _args) do
+ import Supervisor.Spec
+
+ # Define workers and child supervisors to be supervised
+ children = [
+ # Start the Ecto repository
+ supervisor(Update.Repo, []),
+ # Start the endpoint when the application starts
+ supervisor(UpdateWeb.Endpoint, []),
+ # Start your own worker by calling: Update.Worker.start_link(arg1, arg2, arg3)
+ # worker(Update.Worker, [arg1, arg2, arg3]),
+ ]
+
+ # See https://hexdocs.pm/elixir/Supervisor.html
+ # for other strategies and supported options
+ opts = [strategy: :one_for_one, name: Update.Supervisor]
+ Supervisor.start_link(children, opts)
+ end
+
+ # Tell Phoenix to update the endpoint configuration
+ # whenever the application is updated.
+ def config_change(changed, _new, removed) do
+ UpdateWeb.Endpoint.config_change(changed, removed)
+ :ok
+ end
+end
diff --git a/update/lib/update/discussions/comment.ex b/update/lib/update/discussions/comment.ex
new file mode 100644
index 0000000..c6e5f89
--- /dev/null
+++ b/update/lib/update/discussions/comment.ex
@@ -0,0 +1,19 @@
+defmodule Update.Discussions.Comment do
+ use Ecto.Schema
+ import Ecto.Changeset
+ alias Update.Discussions.Comment
+
+
+ schema "comments" do
+ field :content, :string
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(%Comment{} = comment, attrs) do
+ comment
+ |> cast(attrs, [:content])
+ |> validate_required([:content])
+ end
+end
diff --git a/update/lib/update/discussions/discussions.ex b/update/lib/update/discussions/discussions.ex
new file mode 100644
index 0000000..5603c26
--- /dev/null
+++ b/update/lib/update/discussions/discussions.ex
@@ -0,0 +1,200 @@
+defmodule Update.Discussions do
+ @moduledoc """
+ The Discussions context.
+ """
+
+ import Ecto.Query, warn: false
+ alias Update.Repo
+
+ alias Update.Discussions.Topic
+
+ @doc """
+ Returns the list of topics.
+
+ ## Examples
+
+ iex> list_topics()
+ [%Topic{}, ...]
+
+ """
+ def list_topics do
+ Repo.all(Topic)
+ end
+
+ @doc """
+ Gets a single topic.
+
+ Raises `Ecto.NoResultsError` if the Topic does not exist.
+
+ ## Examples
+
+ iex> get_topic!(123)
+ %Topic{}
+
+ iex> get_topic!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_topic!(id), do: Repo.get!(Topic, id)
+
+ @doc """
+ Creates a topic.
+
+ ## Examples
+
+ iex> create_topic(%{field: value})
+ {:ok, %Topic{}}
+
+ iex> create_topic(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_topic(attrs \\ %{}) do
+ %Topic{}
+ |> Topic.changeset(attrs)
+ |> Repo.insert()
+ end
+
+ @doc """
+ Updates a topic.
+
+ ## Examples
+
+ iex> update_topic(topic, %{field: new_value})
+ {:ok, %Topic{}}
+
+ iex> update_topic(topic, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_topic(%Topic{} = topic, attrs) do
+ topic
+ |> Topic.changeset(attrs)
+ |> Repo.update()
+ end
+
+ @doc """
+ Deletes a Topic.
+
+ ## Examples
+
+ iex> delete_topic(topic)
+ {:ok, %Topic{}}
+
+ iex> delete_topic(topic)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_topic(%Topic{} = topic) do
+ Repo.delete(topic)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking topic changes.
+
+ ## Examples
+
+ iex> change_topic(topic)
+ %Ecto.Changeset{source: %Topic{}}
+
+ """
+ def change_topic(%Topic{} = topic) do
+ Topic.changeset(topic, %{})
+ end
+
+ alias Update.Discussions.Comment
+
+ @doc """
+ Returns the list of comments.
+
+ ## Examples
+
+ iex> list_comments()
+ [%Comment{}, ...]
+
+ """
+ def list_comments do
+ Repo.all(Comment)
+ end
+
+ @doc """
+ Gets a single comment.
+
+ Raises `Ecto.NoResultsError` if the Comment does not exist.
+
+ ## Examples
+
+ iex> get_comment!(123)
+ %Comment{}
+
+ iex> get_comment!(456)
+ ** (Ecto.NoResultsError)
+
+ """
+ def get_comment!(id), do: Repo.get!(Comment, id)
+
+ @doc """
+ Creates a comment.
+
+ ## Examples
+
+ iex> create_comment(%{field: value})
+ {:ok, %Comment{}}
+
+ iex> create_comment(%{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def create_comment(attrs \\ %{}) do
+ %Comment{}
+ |> Comment.changeset(attrs)
+ |> Repo.insert()
+ end
+
+ @doc """
+ Updates a comment.
+
+ ## Examples
+
+ iex> update_comment(comment, %{field: new_value})
+ {:ok, %Comment{}}
+
+ iex> update_comment(comment, %{field: bad_value})
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def update_comment(%Comment{} = comment, attrs) do
+ comment
+ |> Comment.changeset(attrs)
+ |> Repo.update()
+ end
+
+ @doc """
+ Deletes a Comment.
+
+ ## Examples
+
+ iex> delete_comment(comment)
+ {:ok, %Comment{}}
+
+ iex> delete_comment(comment)
+ {:error, %Ecto.Changeset{}}
+
+ """
+ def delete_comment(%Comment{} = comment) do
+ Repo.delete(comment)
+ end
+
+ @doc """
+ Returns an `%Ecto.Changeset{}` for tracking comment changes.
+
+ ## Examples
+
+ iex> change_comment(comment)
+ %Ecto.Changeset{source: %Comment{}}
+
+ """
+ def change_comment(%Comment{} = comment) do
+ Comment.changeset(comment, %{})
+ end
+end
diff --git a/update/lib/update/discussions/topic.ex b/update/lib/update/discussions/topic.ex
new file mode 100644
index 0000000..52cfaf9
--- /dev/null
+++ b/update/lib/update/discussions/topic.ex
@@ -0,0 +1,19 @@
+defmodule Update.Discussions.Topic do
+ use Ecto.Schema
+ import Ecto.Changeset
+ alias Update.Discussions.Topic
+
+
+ schema "topics" do
+ field :title, :string
+
+ timestamps()
+ end
+
+ @doc false
+ def changeset(%Topic{} = topic, attrs) do
+ topic
+ |> cast(attrs, [:title])
+ |> validate_required([:title])
+ end
+end
diff --git a/update/lib/update/repo.ex b/update/lib/update/repo.ex
new file mode 100644
index 0000000..7c8c7dd
--- /dev/null
+++ b/update/lib/update/repo.ex
@@ -0,0 +1,11 @@
+defmodule Update.Repo do
+ use Ecto.Repo, otp_app: :update
+
+ @doc """
+ Dynamically loads the repository url from the
+ DATABASE_URL environment variable.
+ """
+ def init(_, opts) do
+ {:ok, Keyword.put(opts, :url, System.get_env("DATABASE_URL"))}
+ end
+end
diff --git a/update/lib/update_web.ex b/update/lib/update_web.ex
new file mode 100644
index 0000000..9077957
--- /dev/null
+++ b/update/lib/update_web.ex
@@ -0,0 +1,67 @@
+defmodule UpdateWeb do
+ @moduledoc """
+ The entrypoint for defining your web interface, such
+ as controllers, views, channels and so on.
+
+ This can be used in your application as:
+
+ use UpdateWeb, :controller
+ use UpdateWeb, :view
+
+ The definitions below will be executed for every view,
+ controller, etc, so keep them short and clean, focused
+ on imports, uses and aliases.
+
+ Do NOT define functions inside the quoted expressions
+ below. Instead, define any helper function in modules
+ and import those modules here.
+ """
+
+ def controller do
+ quote do
+ use Phoenix.Controller, namespace: UpdateWeb
+ import Plug.Conn
+ import UpdateWeb.Router.Helpers
+ import UpdateWeb.Gettext
+ end
+ end
+
+ def view do
+ quote do
+ use Phoenix.View, root: "lib/update_web/templates",
+ namespace: UpdateWeb
+
+ # Import convenience functions from controllers
+ import Phoenix.Controller, only: [get_flash: 2, view_module: 1]
+
+ # Use all HTML functionality (forms, tags, etc)
+ use Phoenix.HTML
+
+ import UpdateWeb.Router.Helpers
+ import UpdateWeb.ErrorHelpers
+ import UpdateWeb.Gettext
+ end
+ end
+
+ def router do
+ quote do
+ use Phoenix.Router
+ import Plug.Conn
+ import Phoenix.Controller
+ end
+ end
+
+ def channel do
+ quote do
+ use Phoenix.Channel
+ import UpdateWeb.Gettext
+ end
+ end
+
+ @doc """
+ When used, dispatch to the appropriate controller/view/etc.
+ """
+ defmacro __using__(which) when is_atom(which) do
+ apply(__MODULE__, which, [])
+ end
+end
diff --git a/update/lib/update_web/channels/user_socket.ex b/update/lib/update_web/channels/user_socket.ex
new file mode 100644
index 0000000..3e3966e
--- /dev/null
+++ b/update/lib/update_web/channels/user_socket.ex
@@ -0,0 +1,37 @@
+defmodule UpdateWeb.UserSocket do
+ use Phoenix.Socket
+
+ ## Channels
+ # channel "room:*", UpdateWeb.RoomChannel
+
+ ## Transports
+ transport :websocket, Phoenix.Transports.WebSocket
+ # transport :longpoll, Phoenix.Transports.LongPoll
+
+ # Socket params are passed from the client and can
+ # be used to verify and authenticate a user. After
+ # verification, you can put default assigns into
+ # the socket that will be set for all channels, ie
+ #
+ # {:ok, assign(socket, :user_id, verified_user_id)}
+ #
+ # To deny connection, return `:error`.
+ #
+ # See `Phoenix.Token` documentation for examples in
+ # performing token verification on connect.
+ def connect(_params, socket) do
+ {:ok, socket}
+ end
+
+ # Socket id's are topics that allow you to identify all sockets for a given user:
+ #
+ # def id(socket), do: "user_socket:#{socket.assigns.user_id}"
+ #
+ # Would allow you to broadcast a "disconnect" event and terminate
+ # all active sockets and channels for a given user:
+ #
+ # UpdateWeb.Endpoint.broadcast("user_socket:#{user.id}", "disconnect", %{})
+ #
+ # Returning `nil` makes this socket anonymous.
+ def id(_socket), do: nil
+end
diff --git a/update/lib/update_web/controllers/comment_controller.ex b/update/lib/update_web/controllers/comment_controller.ex
new file mode 100644
index 0000000..2a5ef1e
--- /dev/null
+++ b/update/lib/update_web/controllers/comment_controller.ex
@@ -0,0 +1,60 @@
+defmodule UpdateWeb.CommentController do
+ use UpdateWeb, :controller
+
+ alias Update.Discussions
+ alias Update.Discussions.Comment
+
+ def index(conn, _params) do
+ comments = Discussions.list_comments()
+ render(conn, "index.html", comments: comments)
+ end
+
+ def new(conn, _params) do
+ changeset = Discussions.change_comment(%Comment{})
+ render(conn, "new.html", changeset: changeset)
+ end
+
+ def create(conn, %{"comment" => comment_params}) do
+ case Discussions.create_comment(comment_params) do
+ {:ok, comment} ->
+ conn
+ |> put_flash(:info, "Comment created successfully.")
+ |> redirect(to: comment_path(conn, :show, comment))
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "new.html", changeset: changeset)
+ end
+ end
+
+ def show(conn, %{"id" => id}) do
+ comment = Discussions.get_comment!(id)
+ render(conn, "show.html", comment: comment)
+ end
+
+ def edit(conn, %{"id" => id}) do
+ comment = Discussions.get_comment!(id)
+ changeset = Discussions.change_comment(comment)
+ render(conn, "edit.html", comment: comment, changeset: changeset)
+ end
+
+ def update(conn, %{"id" => id, "comment" => comment_params}) do
+ comment = Discussions.get_comment!(id)
+
+ case Discussions.update_comment(comment, comment_params) do
+ {:ok, comment} ->
+ conn
+ |> put_flash(:info, "Comment updated successfully.")
+ |> redirect(to: comment_path(conn, :show, comment))
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "edit.html", comment: comment, changeset: changeset)
+ end
+ end
+
+ def delete(conn, %{"id" => id}) do
+ comment = Discussions.get_comment!(id)
+ {:ok, _comment} = Discussions.delete_comment(comment)
+
+ conn
+ |> put_flash(:info, "Comment deleted successfully.")
+ |> redirect(to: comment_path(conn, :index))
+ end
+end
diff --git a/update/lib/update_web/controllers/page_controller.ex b/update/lib/update_web/controllers/page_controller.ex
new file mode 100644
index 0000000..c90af53
--- /dev/null
+++ b/update/lib/update_web/controllers/page_controller.ex
@@ -0,0 +1,7 @@
+defmodule UpdateWeb.PageController do
+ use UpdateWeb, :controller
+
+ def index(conn, _params) do
+ render conn, "index.html"
+ end
+end
diff --git a/update/lib/update_web/controllers/topic_controller.ex b/update/lib/update_web/controllers/topic_controller.ex
new file mode 100644
index 0000000..3d7859a
--- /dev/null
+++ b/update/lib/update_web/controllers/topic_controller.ex
@@ -0,0 +1,60 @@
+defmodule UpdateWeb.TopicController do
+ use UpdateWeb, :controller
+
+ alias Update.Discussions
+ alias Update.Discussions.Topic
+
+ def index(conn, _params) do
+ topics = Discussions.list_topics()
+ render(conn, "index.html", topics: topics)
+ end
+
+ def new(conn, _params) do
+ changeset = Discussions.change_topic(%Topic{})
+ render(conn, "new.html", changeset: changeset)
+ end
+
+ def create(conn, %{"topic" => topic_params}) do
+ case Discussions.create_topic(topic_params) do
+ {:ok, topic} ->
+ conn
+ |> put_flash(:info, "Topic created successfully.")
+ |> redirect(to: topic_path(conn, :show, topic))
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "new.html", changeset: changeset)
+ end
+ end
+
+ def show(conn, %{"id" => id}) do
+ topic = Discussions.get_topic!(id)
+ render(conn, "show.html", topic: topic)
+ end
+
+ def edit(conn, %{"id" => id}) do
+ topic = Discussions.get_topic!(id)
+ changeset = Discussions.change_topic(topic)
+ render(conn, "edit.html", topic: topic, changeset: changeset)
+ end
+
+ def update(conn, %{"id" => id, "topic" => topic_params}) do
+ topic = Discussions.get_topic!(id)
+
+ case Discussions.update_topic(topic, topic_params) do
+ {:ok, topic} ->
+ conn
+ |> put_flash(:info, "Topic updated successfully.")
+ |> redirect(to: topic_path(conn, :show, topic))
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "edit.html", topic: topic, changeset: changeset)
+ end
+ end
+
+ def delete(conn, %{"id" => id}) do
+ topic = Discussions.get_topic!(id)
+ {:ok, _topic} = Discussions.delete_topic(topic)
+
+ conn
+ |> put_flash(:info, "Topic deleted successfully.")
+ |> redirect(to: topic_path(conn, :index))
+ end
+end
diff --git a/update/lib/update_web/controllers/user_controller.ex b/update/lib/update_web/controllers/user_controller.ex
new file mode 100644
index 0000000..098bf59
--- /dev/null
+++ b/update/lib/update_web/controllers/user_controller.ex
@@ -0,0 +1,60 @@
+defmodule UpdateWeb.UserController do
+ use UpdateWeb, :controller
+
+ alias Update.Accounts
+ alias Update.Accounts.User
+
+ def index(conn, _params) do
+ users = Accounts.list_users()
+ render(conn, "index.html", users: users)
+ end
+
+ def new(conn, _params) do
+ changeset = Accounts.change_user(%User{})
+ render(conn, "new.html", changeset: changeset)
+ end
+
+ def create(conn, %{"user" => user_params}) do
+ case Accounts.create_user(user_params) do
+ {:ok, user} ->
+ conn
+ |> put_flash(:info, "User created successfully.")
+ |> redirect(to: user_path(conn, :show, user))
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "new.html", changeset: changeset)
+ end
+ end
+
+ def show(conn, %{"id" => id}) do
+ user = Accounts.get_user!(id)
+ render(conn, "show.html", user: user)
+ end
+
+ def edit(conn, %{"id" => id}) do
+ user = Accounts.get_user!(id)
+ changeset = Accounts.change_user(user)
+ render(conn, "edit.html", user: user, changeset: changeset)
+ end
+
+ def update(conn, %{"id" => id, "user" => user_params}) do
+ user = Accounts.get_user!(id)
+
+ case Accounts.update_user(user, user_params) do
+ {:ok, user} ->
+ conn
+ |> put_flash(:info, "User updated successfully.")
+ |> redirect(to: user_path(conn, :show, user))
+ {:error, %Ecto.Changeset{} = changeset} ->
+ render(conn, "edit.html", user: user, changeset: changeset)
+ end
+ end
+
+ def delete(conn, %{"id" => id}) do
+ user = Accounts.get_user!(id)
+ {:ok, _user} = Accounts.delete_user(user)
+
+ conn
+ |> put_flash(:info, "User deleted successfully.")
+ |> redirect(to: user_path(conn, :index))
+ end
+end
diff --git a/update/lib/update_web/endpoint.ex b/update/lib/update_web/endpoint.ex
new file mode 100644
index 0000000..d326bdd
--- /dev/null
+++ b/update/lib/update_web/endpoint.ex
@@ -0,0 +1,57 @@
+defmodule UpdateWeb.Endpoint do
+ use Phoenix.Endpoint, otp_app: :update
+
+ socket "/socket", UpdateWeb.UserSocket
+
+ # Serve at "/" the static files from "priv/static" directory.
+ #
+ # You should set gzip to true if you are running phoenix.digest
+ # when deploying your static files in production.
+ plug Plug.Static,
+ at: "/", from: :update, gzip: false,
+ only: ~w(css fonts images js favicon.ico robots.txt)
+
+ # Code reloading can be explicitly enabled under the
+ # :code_reloader configuration of your endpoint.
+ if code_reloading? do
+ socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
+ plug Phoenix.LiveReloader
+ plug Phoenix.CodeReloader
+ end
+
+ plug Plug.RequestId
+ plug Plug.Logger
+
+ plug Plug.Parsers,
+ parsers: [:urlencoded, :multipart, :json],
+ pass: ["*/*"],
+ json_decoder: Poison
+
+ plug Plug.MethodOverride
+ plug Plug.Head
+
+ # The session will be stored in the cookie and signed,
+ # this means its contents can be read but not tampered with.
+ # Set :encryption_salt if you would also like to encrypt it.
+ plug Plug.Session,
+ store: :cookie,
+ key: "_update_key",
+ signing_salt: "+q7m+/9E"
+
+ plug UpdateWeb.Router
+
+ @doc """
+ Callback invoked for dynamically configuring the endpoint.
+
+ It receives the endpoint configuration and checks if
+ configuration should be loaded from the system environment.
+ """
+ def init(_key, config) do
+ if config[:load_from_system_env] do
+ port = System.get_env("PORT") || raise "expected the PORT environment variable to be set"
+ {:ok, Keyword.put(config, :http, [:inet6, port: port])}
+ else
+ {:ok, config}
+ end
+ end
+end
diff --git a/update/lib/update_web/gettext.ex b/update/lib/update_web/gettext.ex
new file mode 100644
index 0000000..7979338
--- /dev/null
+++ b/update/lib/update_web/gettext.ex
@@ -0,0 +1,24 @@
+defmodule UpdateWeb.Gettext do
+ @moduledoc """
+ A module providing Internationalization with a gettext-based API.
+
+ By using [Gettext](https://hexdocs.pm/gettext),
+ your module gains a set of macros for translations, for example:
+
+ import UpdateWeb.Gettext
+
+ # Simple translation
+ gettext "Here is the string to translate"
+
+ # Plural translation
+ ngettext "Here is the string to translate",
+ "Here are the strings to translate",
+ 3
+
+ # Domain-based translation
+ dgettext "errors", "Here is the error message to translate"
+
+ See the [Gettext Docs](https://hexdocs.pm/gettext) for detailed usage.
+ """
+ use Gettext, otp_app: :update
+end
diff --git a/update/lib/update_web/router.ex b/update/lib/update_web/router.ex
new file mode 100644
index 0000000..3a4113d
--- /dev/null
+++ b/update/lib/update_web/router.ex
@@ -0,0 +1,26 @@
+defmodule UpdateWeb.Router do
+ use UpdateWeb, :router
+
+ pipeline :browser do
+ plug :accepts, ["html"]
+ plug :fetch_session
+ plug :fetch_flash
+ plug :protect_from_forgery
+ plug :put_secure_browser_headers
+ end
+
+ pipeline :api do
+ plug :accepts, ["json"]
+ end
+
+ scope "/", UpdateWeb do
+ pipe_through :browser # Use the default browser stack
+
+ get "/", PageController, :index
+ end
+
+ # Other scopes may use custom stacks.
+ # scope "/api", UpdateWeb do
+ # pipe_through :api
+ # end
+end
diff --git a/update/lib/update_web/templates/comment/edit.html.eex b/update/lib/update_web/templates/comment/edit.html.eex
new file mode 100644
index 0000000..f9cb7d9
--- /dev/null
+++ b/update/lib/update_web/templates/comment/edit.html.eex
@@ -0,0 +1,5 @@
+Edit Comment
+
+<%= render "form.html", Map.put(assigns, :action, comment_path(@conn, :update, @comment)) %>
+
+<%= link "Back", to: comment_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/comment/form.html.eex b/update/lib/update_web/templates/comment/form.html.eex
new file mode 100644
index 0000000..e7ac690
--- /dev/null
+++ b/update/lib/update_web/templates/comment/form.html.eex
@@ -0,0 +1,17 @@
+<%= form_for @changeset, @action, fn f -> %>
+ <%= if @changeset.action do %>
+
+
Oops, something went wrong! Please check the errors below.
+
+ <% end %>
+
+
+ <%= label f, :content, class: "control-label" %>
+ <%= text_input f, :content, class: "form-control" %>
+ <%= error_tag f, :content %>
+
+
+
+ <%= submit "Submit", class: "btn btn-primary" %>
+
+<% end %>
diff --git a/update/lib/update_web/templates/comment/index.html.eex b/update/lib/update_web/templates/comment/index.html.eex
new file mode 100644
index 0000000..27dfc8d
--- /dev/null
+++ b/update/lib/update_web/templates/comment/index.html.eex
@@ -0,0 +1,26 @@
+Listing Comments
+
+
+
+
+ Content
+
+
+
+
+
+<%= for comment <- @comments do %>
+
+ <%= comment.content %>
+
+
+ <%= link "Show", to: comment_path(@conn, :show, comment), class: "btn btn-default btn-xs" %>
+ <%= link "Edit", to: comment_path(@conn, :edit, comment), class: "btn btn-default btn-xs" %>
+ <%= link "Delete", to: comment_path(@conn, :delete, comment), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger btn-xs" %>
+
+
+<% end %>
+
+
+
+<%= link "New Comment", to: comment_path(@conn, :new) %>
diff --git a/update/lib/update_web/templates/comment/new.html.eex b/update/lib/update_web/templates/comment/new.html.eex
new file mode 100644
index 0000000..0425f5a
--- /dev/null
+++ b/update/lib/update_web/templates/comment/new.html.eex
@@ -0,0 +1,5 @@
+New Comment
+
+<%= render "form.html", Map.put(assigns, :action, comment_path(@conn, :create)) %>
+
+<%= link "Back", to: comment_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/comment/show.html.eex b/update/lib/update_web/templates/comment/show.html.eex
new file mode 100644
index 0000000..d05c1cd
--- /dev/null
+++ b/update/lib/update_web/templates/comment/show.html.eex
@@ -0,0 +1,13 @@
+Show Comment
+
+
+
+
+ Content:
+ <%= @comment.content %>
+
+
+
+
+<%= link "Edit", to: comment_path(@conn, :edit, @comment) %>
+<%= link "Back", to: comment_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/layout/app.html.eex b/update/lib/update_web/templates/layout/app.html.eex
new file mode 100644
index 0000000..2cbc427
--- /dev/null
+++ b/update/lib/update_web/templates/layout/app.html.eex
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+ Hello Update!
+ ">
+
+
+
+
+
+
+
<%= get_flash(@conn, :info) %>
+
<%= get_flash(@conn, :error) %>
+
+
+ <%= render @view_module, @view_template, assigns %>
+
+
+
+
+
+
diff --git a/update/lib/update_web/templates/page/index.html.eex b/update/lib/update_web/templates/page/index.html.eex
new file mode 100644
index 0000000..0988ea5
--- /dev/null
+++ b/update/lib/update_web/templates/page/index.html.eex
@@ -0,0 +1,36 @@
+
+
<%= gettext "Welcome to %{name}!", name: "Phoenix" %>
+
A productive web framework that does not compromise speed and maintainability.
+
+
+
diff --git a/update/lib/update_web/templates/topic/edit.html.eex b/update/lib/update_web/templates/topic/edit.html.eex
new file mode 100644
index 0000000..f660bdb
--- /dev/null
+++ b/update/lib/update_web/templates/topic/edit.html.eex
@@ -0,0 +1,5 @@
+Edit Topic
+
+<%= render "form.html", Map.put(assigns, :action, topic_path(@conn, :update, @topic)) %>
+
+<%= link "Back", to: topic_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/topic/form.html.eex b/update/lib/update_web/templates/topic/form.html.eex
new file mode 100644
index 0000000..1912b19
--- /dev/null
+++ b/update/lib/update_web/templates/topic/form.html.eex
@@ -0,0 +1,17 @@
+<%= form_for @changeset, @action, fn f -> %>
+ <%= if @changeset.action do %>
+
+
Oops, something went wrong! Please check the errors below.
+
+ <% end %>
+
+
+ <%= label f, :title, class: "control-label" %>
+ <%= text_input f, :title, class: "form-control" %>
+ <%= error_tag f, :title %>
+
+
+
+ <%= submit "Submit", class: "btn btn-primary" %>
+
+<% end %>
diff --git a/update/lib/update_web/templates/topic/index.html.eex b/update/lib/update_web/templates/topic/index.html.eex
new file mode 100644
index 0000000..a893329
--- /dev/null
+++ b/update/lib/update_web/templates/topic/index.html.eex
@@ -0,0 +1,26 @@
+Listing Topics
+
+
+
+
+ Title
+
+
+
+
+
+<%= for topic <- @topics do %>
+
+ <%= topic.title %>
+
+
+ <%= link "Show", to: topic_path(@conn, :show, topic), class: "btn btn-default btn-xs" %>
+ <%= link "Edit", to: topic_path(@conn, :edit, topic), class: "btn btn-default btn-xs" %>
+ <%= link "Delete", to: topic_path(@conn, :delete, topic), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger btn-xs" %>
+
+
+<% end %>
+
+
+
+<%= link "New Topic", to: topic_path(@conn, :new) %>
diff --git a/update/lib/update_web/templates/topic/new.html.eex b/update/lib/update_web/templates/topic/new.html.eex
new file mode 100644
index 0000000..8798eed
--- /dev/null
+++ b/update/lib/update_web/templates/topic/new.html.eex
@@ -0,0 +1,5 @@
+New Topic
+
+<%= render "form.html", Map.put(assigns, :action, topic_path(@conn, :create)) %>
+
+<%= link "Back", to: topic_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/topic/show.html.eex b/update/lib/update_web/templates/topic/show.html.eex
new file mode 100644
index 0000000..6b5985f
--- /dev/null
+++ b/update/lib/update_web/templates/topic/show.html.eex
@@ -0,0 +1,13 @@
+Show Topic
+
+
+
+
+ Title:
+ <%= @topic.title %>
+
+
+
+
+<%= link "Edit", to: topic_path(@conn, :edit, @topic) %>
+<%= link "Back", to: topic_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/user/edit.html.eex b/update/lib/update_web/templates/user/edit.html.eex
new file mode 100644
index 0000000..338ced8
--- /dev/null
+++ b/update/lib/update_web/templates/user/edit.html.eex
@@ -0,0 +1,5 @@
+Edit User
+
+<%= render "form.html", Map.put(assigns, :action, user_path(@conn, :update, @user)) %>
+
+<%= link "Back", to: user_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/user/form.html.eex b/update/lib/update_web/templates/user/form.html.eex
new file mode 100644
index 0000000..5262651
--- /dev/null
+++ b/update/lib/update_web/templates/user/form.html.eex
@@ -0,0 +1,17 @@
+<%= form_for @changeset, @action, fn f -> %>
+ <%= if @changeset.action do %>
+
+
Oops, something went wrong! Please check the errors below.
+
+ <% end %>
+
+
+ <%= label f, :email, class: "control-label" %>
+ <%= text_input f, :email, class: "form-control" %>
+ <%= error_tag f, :email %>
+
+
+
+ <%= submit "Submit", class: "btn btn-primary" %>
+
+<% end %>
diff --git a/update/lib/update_web/templates/user/index.html.eex b/update/lib/update_web/templates/user/index.html.eex
new file mode 100644
index 0000000..508d87c
--- /dev/null
+++ b/update/lib/update_web/templates/user/index.html.eex
@@ -0,0 +1,26 @@
+Listing Users
+
+
+
+
+ Email
+
+
+
+
+
+<%= for user <- @users do %>
+
+ <%= user.email %>
+
+
+ <%= link "Show", to: user_path(@conn, :show, user), class: "btn btn-default btn-xs" %>
+ <%= link "Edit", to: user_path(@conn, :edit, user), class: "btn btn-default btn-xs" %>
+ <%= link "Delete", to: user_path(@conn, :delete, user), method: :delete, data: [confirm: "Are you sure?"], class: "btn btn-danger btn-xs" %>
+
+
+<% end %>
+
+
+
+<%= link "New User", to: user_path(@conn, :new) %>
diff --git a/update/lib/update_web/templates/user/new.html.eex b/update/lib/update_web/templates/user/new.html.eex
new file mode 100644
index 0000000..95a34c2
--- /dev/null
+++ b/update/lib/update_web/templates/user/new.html.eex
@@ -0,0 +1,5 @@
+New User
+
+<%= render "form.html", Map.put(assigns, :action, user_path(@conn, :create)) %>
+
+<%= link "Back", to: user_path(@conn, :index) %>
diff --git a/update/lib/update_web/templates/user/show.html.eex b/update/lib/update_web/templates/user/show.html.eex
new file mode 100644
index 0000000..65fc7ec
--- /dev/null
+++ b/update/lib/update_web/templates/user/show.html.eex
@@ -0,0 +1,13 @@
+Show User
+
+
+
+
+ Email:
+ <%= @user.email %>
+
+
+
+
+<%= link "Edit", to: user_path(@conn, :edit, @user) %>
+<%= link "Back", to: user_path(@conn, :index) %>
diff --git a/update/lib/update_web/views/comment_view.ex b/update/lib/update_web/views/comment_view.ex
new file mode 100644
index 0000000..b11bdd3
--- /dev/null
+++ b/update/lib/update_web/views/comment_view.ex
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.CommentView do
+ use UpdateWeb, :view
+end
diff --git a/update/lib/update_web/views/error_helpers.ex b/update/lib/update_web/views/error_helpers.ex
new file mode 100644
index 0000000..de35ae7
--- /dev/null
+++ b/update/lib/update_web/views/error_helpers.ex
@@ -0,0 +1,40 @@
+defmodule UpdateWeb.ErrorHelpers do
+ @moduledoc """
+ Conveniences for translating and building error messages.
+ """
+
+ use Phoenix.HTML
+
+ @doc """
+ Generates tag for inlined form input errors.
+ """
+ def error_tag(form, field) do
+ Enum.map(Keyword.get_values(form.errors, field), fn (error) ->
+ content_tag :span, translate_error(error), class: "help-block"
+ end)
+ end
+
+ @doc """
+ Translates an error message using gettext.
+ """
+ def translate_error({msg, opts}) do
+ # Because error messages were defined within Ecto, we must
+ # call the Gettext module passing our Gettext backend. We
+ # also use the "errors" domain as translations are placed
+ # in the errors.po file.
+ # Ecto will pass the :count keyword if the error message is
+ # meant to be pluralized.
+ # On your own code and templates, depending on whether you
+ # need the message to be pluralized or not, this could be
+ # written simply as:
+ #
+ # dngettext "errors", "1 file", "%{count} files", count
+ # dgettext "errors", "is invalid"
+ #
+ if count = opts[:count] do
+ Gettext.dngettext(UpdateWeb.Gettext, "errors", msg, msg, count, opts)
+ else
+ Gettext.dgettext(UpdateWeb.Gettext, "errors", msg, opts)
+ end
+ end
+end
diff --git a/update/lib/update_web/views/error_view.ex b/update/lib/update_web/views/error_view.ex
new file mode 100644
index 0000000..0fa4d02
--- /dev/null
+++ b/update/lib/update_web/views/error_view.ex
@@ -0,0 +1,17 @@
+defmodule UpdateWeb.ErrorView do
+ use UpdateWeb, :view
+
+ def render("404.html", _assigns) do
+ "Page not found"
+ end
+
+ def render("500.html", _assigns) do
+ "Internal server error"
+ end
+
+ # In case no render clause matches or no
+ # template is found, let's render it as 500
+ def template_not_found(_template, assigns) do
+ render "500.html", assigns
+ end
+end
diff --git a/update/lib/update_web/views/layout_view.ex b/update/lib/update_web/views/layout_view.ex
new file mode 100644
index 0000000..d0cb357
--- /dev/null
+++ b/update/lib/update_web/views/layout_view.ex
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.LayoutView do
+ use UpdateWeb, :view
+end
diff --git a/update/lib/update_web/views/page_view.ex b/update/lib/update_web/views/page_view.ex
new file mode 100644
index 0000000..89b0880
--- /dev/null
+++ b/update/lib/update_web/views/page_view.ex
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.PageView do
+ use UpdateWeb, :view
+end
diff --git a/update/lib/update_web/views/topic_view.ex b/update/lib/update_web/views/topic_view.ex
new file mode 100644
index 0000000..c1ab7c2
--- /dev/null
+++ b/update/lib/update_web/views/topic_view.ex
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.TopicView do
+ use UpdateWeb, :view
+end
diff --git a/update/lib/update_web/views/user_view.ex b/update/lib/update_web/views/user_view.ex
new file mode 100644
index 0000000..9e1defa
--- /dev/null
+++ b/update/lib/update_web/views/user_view.ex
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.UserView do
+ use UpdateWeb, :view
+end
diff --git a/update/mix.exs b/update/mix.exs
new file mode 100644
index 0000000..1c13a76
--- /dev/null
+++ b/update/mix.exs
@@ -0,0 +1,60 @@
+defmodule Update.Mixfile do
+ use Mix.Project
+
+ def project do
+ [
+ app: :update,
+ version: "0.0.1",
+ elixir: "~> 1.4",
+ elixirc_paths: elixirc_paths(Mix.env),
+ compilers: [:phoenix, :gettext] ++ Mix.compilers,
+ start_permanent: Mix.env == :prod,
+ aliases: aliases(),
+ deps: deps()
+ ]
+ end
+
+ # Configuration for the OTP application.
+ #
+ # Type `mix help compile.app` for more information.
+ def application do
+ [
+ mod: {Update.Application, []},
+ extra_applications: [:logger, :runtime_tools]
+ ]
+ end
+
+ # Specifies which paths to compile per environment.
+ defp elixirc_paths(:test), do: ["lib", "test/support"]
+ defp elixirc_paths(_), do: ["lib"]
+
+ # Specifies your project dependencies.
+ #
+ # Type `mix help deps` for examples and options.
+ defp deps do
+ [
+ {:phoenix, "~> 1.3.0"},
+ {:phoenix_pubsub, "~> 1.0"},
+ {:phoenix_ecto, "~> 3.2"},
+ {:postgrex, ">= 0.0.0"},
+ {:phoenix_html, "~> 2.10"},
+ {:phoenix_live_reload, "~> 1.0", only: :dev},
+ {:gettext, "~> 0.11"},
+ {:cowboy, "~> 1.0"}
+ ]
+ end
+
+ # Aliases are shortcuts or tasks specific to the current project.
+ # For example, to create, migrate and run the seeds file at once:
+ #
+ # $ mix ecto.setup
+ #
+ # See the documentation for `Mix` for more info on aliases.
+ defp aliases do
+ [
+ "ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
+ "ecto.reset": ["ecto.drop", "ecto.setup"],
+ "test": ["ecto.create --quiet", "ecto.migrate", "test"]
+ ]
+ end
+end
diff --git a/update/mix.lock b/update/mix.lock
new file mode 100644
index 0000000..9448ccf
--- /dev/null
+++ b/update/mix.lock
@@ -0,0 +1,19 @@
+%{"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [], [], "hexpm"},
+ "cowboy": {:hex, :cowboy, "1.1.2", "61ac29ea970389a88eca5a65601460162d370a70018afe6f949a29dca91f3bb0", [], [{:cowlib, "~> 1.0.2", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3.2", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"},
+ "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [], [], "hexpm"},
+ "db_connection": {:hex, :db_connection, "1.1.2", "2865c2a4bae0714e2213a0ce60a1b12d76a6efba0c51fbda59c9ab8d1accc7a8", [], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
+ "decimal": {:hex, :decimal, "1.4.0", "fac965ce71a46aab53d3a6ce45662806bdd708a4a95a65cde8a12eb0124a1333", [], [], "hexpm"},
+ "ecto": {:hex, :ecto, "2.2.2", "e9bd6ebc044eaaab1cb369e3465686d8aca830aa5bf545ef2bae000a3d42c54b", [], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"},
+ "file_system": {:hex, :file_system, "0.2.1", "c4bec8f187d2aabace4beb890f0d4e468f65ca051593db768e533a274d0df587", [], [], "hexpm"},
+ "gettext": {:hex, :gettext, "0.13.1", "5e0daf4e7636d771c4c71ad5f3f53ba09a9ae5c250e1ab9c42ba9edccc476263", [], [], "hexpm"},
+ "mime": {:hex, :mime, "1.1.0", "01c1d6f4083d8aa5c7b8c246ade95139620ef8effb009edde934e0ec3b28090a", [], [], "hexpm"},
+ "phoenix": {:hex, :phoenix, "1.3.0", "1c01124caa1b4a7af46f2050ff11b267baa3edb441b45dbf243e979cd4c5891b", [], [{:cowboy, "~> 1.0", [hex: :cowboy, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: false]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_ecto": {:hex, :phoenix_ecto, "3.2.3", "450c749876ff1de4a78fdb305a142a76817c77a1cd79aeca29e5fc9a6c630b26", [], [{:ecto, "~> 2.1", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_html": {:hex, :phoenix_html, "2.10.4", "d4f99c32d5dc4918b531fdf163e1fd7cf20acdd7703f16f5d02d4db36de803b7", [], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_live_reload": {:hex, :phoenix_live_reload, "1.1.1", "8c9f0fb95d5592f3769f83fda852d3aab806309c946831f7e50fe447c2859e13", [], [{:file_system, "~> 0.2", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.0", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm"},
+ "phoenix_pubsub": {:hex, :phoenix_pubsub, "1.0.2", "bfa7fd52788b5eaa09cb51ff9fcad1d9edfeb68251add458523f839392f034c1", [], [], "hexpm"},
+ "plug": {:hex, :plug, "1.4.3", "236d77ce7bf3e3a2668dc0d32a9b6f1f9b1f05361019946aae49874904be4aed", [], [{:cowboy, "~> 1.0.1 or ~> 1.1", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
+ "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [], [], "hexpm"},
+ "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [], [], "hexpm"},
+ "postgrex": {:hex, :postgrex, "0.13.3", "c277cfb2a9c5034d445a722494c13359e361d344ef6f25d604c2353185682bfc", [], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm"},
+ "ranch": {:hex, :ranch, "1.3.2", "e4965a144dc9fbe70e5c077c65e73c57165416a901bd02ea899cfd95aa890986", [], [], "hexpm"}}
diff --git a/update/priv/gettext/en/LC_MESSAGES/errors.po b/update/priv/gettext/en/LC_MESSAGES/errors.po
new file mode 100644
index 0000000..a589998
--- /dev/null
+++ b/update/priv/gettext/en/LC_MESSAGES/errors.po
@@ -0,0 +1,97 @@
+## `msgid`s in this file come from POT (.pot) files.
+##
+## Do not add, change, or remove `msgid`s manually here as
+## they're tied to the ones in the corresponding POT file
+## (with the same domain).
+##
+## Use `mix gettext.extract --merge` or `mix gettext.merge`
+## to merge POT files into PO files.
+msgid ""
+msgstr ""
+"Language: en\n"
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_acceptance/3
+msgid "must be accepted"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated with this entry"
+msgstr ""
+
+msgid "are still associated with this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/update/priv/gettext/errors.pot b/update/priv/gettext/errors.pot
new file mode 100644
index 0000000..7b2d5ca
--- /dev/null
+++ b/update/priv/gettext/errors.pot
@@ -0,0 +1,95 @@
+## This file is a PO Template file.
+##
+## `msgid`s here are often extracted from source code.
+## Add new translations manually only if they're dynamic
+## translations that can't be statically extracted.
+##
+## Run `mix gettext.extract` to bring this file up to
+## date. Leave `msgstr`s empty as changing them here as no
+## effect: edit them in PO (`.po`) files instead.
+
+## From Ecto.Changeset.cast/4
+msgid "can't be blank"
+msgstr ""
+
+## From Ecto.Changeset.unique_constraint/3
+msgid "has already been taken"
+msgstr ""
+
+## From Ecto.Changeset.put_change/3
+msgid "is invalid"
+msgstr ""
+
+## From Ecto.Changeset.validate_acceptance/3
+msgid "must be accepted"
+msgstr ""
+
+## From Ecto.Changeset.validate_format/3
+msgid "has invalid format"
+msgstr ""
+
+## From Ecto.Changeset.validate_subset/3
+msgid "has an invalid entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_exclusion/3
+msgid "is reserved"
+msgstr ""
+
+## From Ecto.Changeset.validate_confirmation/3
+msgid "does not match confirmation"
+msgstr ""
+
+## From Ecto.Changeset.no_assoc_constraint/3
+msgid "is still associated with this entry"
+msgstr ""
+
+msgid "are still associated with this entry"
+msgstr ""
+
+## From Ecto.Changeset.validate_length/3
+msgid "should be %{count} character(s)"
+msgid_plural "should be %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have %{count} item(s)"
+msgid_plural "should have %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at least %{count} character(s)"
+msgid_plural "should be at least %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at least %{count} item(s)"
+msgid_plural "should have at least %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should be at most %{count} character(s)"
+msgid_plural "should be at most %{count} character(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "should have at most %{count} item(s)"
+msgid_plural "should have at most %{count} item(s)"
+msgstr[0] ""
+msgstr[1] ""
+
+## From Ecto.Changeset.validate_number/3
+msgid "must be less than %{number}"
+msgstr ""
+
+msgid "must be greater than %{number}"
+msgstr ""
+
+msgid "must be less than or equal to %{number}"
+msgstr ""
+
+msgid "must be greater than or equal to %{number}"
+msgstr ""
+
+msgid "must be equal to %{number}"
+msgstr ""
diff --git a/update/priv/repo/migrations/20170911234511_create_users.exs b/update/priv/repo/migrations/20170911234511_create_users.exs
new file mode 100644
index 0000000..fb145d9
--- /dev/null
+++ b/update/priv/repo/migrations/20170911234511_create_users.exs
@@ -0,0 +1,12 @@
+defmodule Update.Repo.Migrations.CreateUsers do
+ use Ecto.Migration
+
+ def change do
+ create table(:users) do
+ add :email, :string
+
+ timestamps()
+ end
+
+ end
+end
diff --git a/update/priv/repo/migrations/20170911234518_create_topics.exs b/update/priv/repo/migrations/20170911234518_create_topics.exs
new file mode 100644
index 0000000..fc67f67
--- /dev/null
+++ b/update/priv/repo/migrations/20170911234518_create_topics.exs
@@ -0,0 +1,12 @@
+defmodule Update.Repo.Migrations.CreateTopics do
+ use Ecto.Migration
+
+ def change do
+ create table(:topics) do
+ add :title, :string
+
+ timestamps()
+ end
+
+ end
+end
diff --git a/update/priv/repo/migrations/20170911234524_create_comments.exs b/update/priv/repo/migrations/20170911234524_create_comments.exs
new file mode 100644
index 0000000..5168256
--- /dev/null
+++ b/update/priv/repo/migrations/20170911234524_create_comments.exs
@@ -0,0 +1,12 @@
+defmodule Update.Repo.Migrations.CreateComments do
+ use Ecto.Migration
+
+ def change do
+ create table(:comments) do
+ add :content, :string
+
+ timestamps()
+ end
+
+ end
+end
diff --git a/update/priv/repo/seeds.exs b/update/priv/repo/seeds.exs
new file mode 100644
index 0000000..2db1967
--- /dev/null
+++ b/update/priv/repo/seeds.exs
@@ -0,0 +1,11 @@
+# Script for populating the database. You can run it as:
+#
+# mix run priv/repo/seeds.exs
+#
+# Inside the script, you can read and write to any of your
+# repositories directly:
+#
+# Update.Repo.insert!(%Update.SomeSchema{})
+#
+# We recommend using the bang functions (`insert!`, `update!`
+# and so on) as they will fail if something goes wrong.
diff --git a/update/test/support/channel_case.ex b/update/test/support/channel_case.ex
new file mode 100644
index 0000000..3724590
--- /dev/null
+++ b/update/test/support/channel_case.ex
@@ -0,0 +1,37 @@
+defmodule UpdateWeb.ChannelCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ channel tests.
+
+ Such tests rely on `Phoenix.ChannelTest` and also
+ import other functionality to make it easier
+ to build common datastructures and query the data layer.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with channels
+ use Phoenix.ChannelTest
+
+ # The default endpoint for testing
+ @endpoint UpdateWeb.Endpoint
+ end
+ end
+
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Update.Repo)
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Update.Repo, {:shared, self()})
+ end
+ :ok
+ end
+
+end
diff --git a/update/test/support/conn_case.ex b/update/test/support/conn_case.ex
new file mode 100644
index 0000000..7dbc091
--- /dev/null
+++ b/update/test/support/conn_case.ex
@@ -0,0 +1,38 @@
+defmodule UpdateWeb.ConnCase do
+ @moduledoc """
+ This module defines the test case to be used by
+ tests that require setting up a connection.
+
+ Such tests rely on `Phoenix.ConnTest` and also
+ import other functionality to make it easier
+ to build common datastructures and query the data layer.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ # Import conveniences for testing with connections
+ use Phoenix.ConnTest
+ import UpdateWeb.Router.Helpers
+
+ # The default endpoint for testing
+ @endpoint UpdateWeb.Endpoint
+ end
+ end
+
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Update.Repo)
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Update.Repo, {:shared, self()})
+ end
+ {:ok, conn: Phoenix.ConnTest.build_conn()}
+ end
+
+end
diff --git a/update/test/support/data_case.ex b/update/test/support/data_case.ex
new file mode 100644
index 0000000..d0ad8d0
--- /dev/null
+++ b/update/test/support/data_case.ex
@@ -0,0 +1,53 @@
+defmodule Update.DataCase do
+ @moduledoc """
+ This module defines the setup for tests requiring
+ access to the application's data layer.
+
+ You may define functions here to be used as helpers in
+ your tests.
+
+ Finally, if the test case interacts with the database,
+ it cannot be async. For this reason, every test runs
+ inside a transaction which is reset at the beginning
+ of the test unless the test case is marked as async.
+ """
+
+ use ExUnit.CaseTemplate
+
+ using do
+ quote do
+ alias Update.Repo
+
+ import Ecto
+ import Ecto.Changeset
+ import Ecto.Query
+ import Update.DataCase
+ end
+ end
+
+ setup tags do
+ :ok = Ecto.Adapters.SQL.Sandbox.checkout(Update.Repo)
+
+ unless tags[:async] do
+ Ecto.Adapters.SQL.Sandbox.mode(Update.Repo, {:shared, self()})
+ end
+
+ :ok
+ end
+
+ @doc """
+ A helper that transform changeset errors to a map of messages.
+
+ assert {:error, changeset} = Accounts.create_user(%{password: "short"})
+ assert "password is too short" in errors_on(changeset).password
+ assert %{password: ["password is too short"]} = errors_on(changeset)
+
+ """
+ def errors_on(changeset) do
+ Ecto.Changeset.traverse_errors(changeset, fn {message, opts} ->
+ Enum.reduce(opts, message, fn {key, value}, acc ->
+ String.replace(acc, "%{#{key}}", to_string(value))
+ end)
+ end)
+ end
+end
diff --git a/update/test/test_helper.exs b/update/test/test_helper.exs
new file mode 100644
index 0000000..8ad4e76
--- /dev/null
+++ b/update/test/test_helper.exs
@@ -0,0 +1,4 @@
+ExUnit.start()
+
+Ecto.Adapters.SQL.Sandbox.mode(Update.Repo, :manual)
+
diff --git a/update/test/update/accounts/accounts_test.exs b/update/test/update/accounts/accounts_test.exs
new file mode 100644
index 0000000..f7e2410
--- /dev/null
+++ b/update/test/update/accounts/accounts_test.exs
@@ -0,0 +1,65 @@
+defmodule Update.AccountsTest do
+ use Update.DataCase
+
+ alias Update.Accounts
+
+ describe "users" do
+ alias Update.Accounts.User
+
+ @valid_attrs %{email: "some email"}
+ @update_attrs %{email: "some updated email"}
+ @invalid_attrs %{email: nil}
+
+ def user_fixture(attrs \\ %{}) do
+ {:ok, user} =
+ attrs
+ |> Enum.into(@valid_attrs)
+ |> Accounts.create_user()
+
+ user
+ end
+
+ test "list_users/0 returns all users" do
+ user = user_fixture()
+ assert Accounts.list_users() == [user]
+ end
+
+ test "get_user!/1 returns the user with given id" do
+ user = user_fixture()
+ assert Accounts.get_user!(user.id) == user
+ end
+
+ test "create_user/1 with valid data creates a user" do
+ assert {:ok, %User{} = user} = Accounts.create_user(@valid_attrs)
+ assert user.email == "some email"
+ end
+
+ test "create_user/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Accounts.create_user(@invalid_attrs)
+ end
+
+ test "update_user/2 with valid data updates the user" do
+ user = user_fixture()
+ assert {:ok, user} = Accounts.update_user(user, @update_attrs)
+ assert %User{} = user
+ assert user.email == "some updated email"
+ end
+
+ test "update_user/2 with invalid data returns error changeset" do
+ user = user_fixture()
+ assert {:error, %Ecto.Changeset{}} = Accounts.update_user(user, @invalid_attrs)
+ assert user == Accounts.get_user!(user.id)
+ end
+
+ test "delete_user/1 deletes the user" do
+ user = user_fixture()
+ assert {:ok, %User{}} = Accounts.delete_user(user)
+ assert_raise Ecto.NoResultsError, fn -> Accounts.get_user!(user.id) end
+ end
+
+ test "change_user/1 returns a user changeset" do
+ user = user_fixture()
+ assert %Ecto.Changeset{} = Accounts.change_user(user)
+ end
+ end
+end
diff --git a/update/test/update/discussions/discussions_test.exs b/update/test/update/discussions/discussions_test.exs
new file mode 100644
index 0000000..9ed00d5
--- /dev/null
+++ b/update/test/update/discussions/discussions_test.exs
@@ -0,0 +1,125 @@
+defmodule Update.DiscussionsTest do
+ use Update.DataCase
+
+ alias Update.Discussions
+
+ describe "topics" do
+ alias Update.Discussions.Topic
+
+ @valid_attrs %{title: "some title"}
+ @update_attrs %{title: "some updated title"}
+ @invalid_attrs %{title: nil}
+
+ def topic_fixture(attrs \\ %{}) do
+ {:ok, topic} =
+ attrs
+ |> Enum.into(@valid_attrs)
+ |> Discussions.create_topic()
+
+ topic
+ end
+
+ test "list_topics/0 returns all topics" do
+ topic = topic_fixture()
+ assert Discussions.list_topics() == [topic]
+ end
+
+ test "get_topic!/1 returns the topic with given id" do
+ topic = topic_fixture()
+ assert Discussions.get_topic!(topic.id) == topic
+ end
+
+ test "create_topic/1 with valid data creates a topic" do
+ assert {:ok, %Topic{} = topic} = Discussions.create_topic(@valid_attrs)
+ assert topic.title == "some title"
+ end
+
+ test "create_topic/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Discussions.create_topic(@invalid_attrs)
+ end
+
+ test "update_topic/2 with valid data updates the topic" do
+ topic = topic_fixture()
+ assert {:ok, topic} = Discussions.update_topic(topic, @update_attrs)
+ assert %Topic{} = topic
+ assert topic.title == "some updated title"
+ end
+
+ test "update_topic/2 with invalid data returns error changeset" do
+ topic = topic_fixture()
+ assert {:error, %Ecto.Changeset{}} = Discussions.update_topic(topic, @invalid_attrs)
+ assert topic == Discussions.get_topic!(topic.id)
+ end
+
+ test "delete_topic/1 deletes the topic" do
+ topic = topic_fixture()
+ assert {:ok, %Topic{}} = Discussions.delete_topic(topic)
+ assert_raise Ecto.NoResultsError, fn -> Discussions.get_topic!(topic.id) end
+ end
+
+ test "change_topic/1 returns a topic changeset" do
+ topic = topic_fixture()
+ assert %Ecto.Changeset{} = Discussions.change_topic(topic)
+ end
+ end
+
+ describe "comments" do
+ alias Update.Discussions.Comment
+
+ @valid_attrs %{content: "some content"}
+ @update_attrs %{content: "some updated content"}
+ @invalid_attrs %{content: nil}
+
+ def comment_fixture(attrs \\ %{}) do
+ {:ok, comment} =
+ attrs
+ |> Enum.into(@valid_attrs)
+ |> Discussions.create_comment()
+
+ comment
+ end
+
+ test "list_comments/0 returns all comments" do
+ comment = comment_fixture()
+ assert Discussions.list_comments() == [comment]
+ end
+
+ test "get_comment!/1 returns the comment with given id" do
+ comment = comment_fixture()
+ assert Discussions.get_comment!(comment.id) == comment
+ end
+
+ test "create_comment/1 with valid data creates a comment" do
+ assert {:ok, %Comment{} = comment} = Discussions.create_comment(@valid_attrs)
+ assert comment.content == "some content"
+ end
+
+ test "create_comment/1 with invalid data returns error changeset" do
+ assert {:error, %Ecto.Changeset{}} = Discussions.create_comment(@invalid_attrs)
+ end
+
+ test "update_comment/2 with valid data updates the comment" do
+ comment = comment_fixture()
+ assert {:ok, comment} = Discussions.update_comment(comment, @update_attrs)
+ assert %Comment{} = comment
+ assert comment.content == "some updated content"
+ end
+
+ test "update_comment/2 with invalid data returns error changeset" do
+ comment = comment_fixture()
+ assert {:error, %Ecto.Changeset{}} = Discussions.update_comment(comment, @invalid_attrs)
+ assert comment == Discussions.get_comment!(comment.id)
+ end
+
+ test "delete_comment/1 deletes the comment" do
+ comment = comment_fixture()
+ assert {:ok, %Comment{}} = Discussions.delete_comment(comment)
+ assert_raise Ecto.NoResultsError, fn -> Discussions.get_comment!(comment.id) end
+ end
+
+ test "change_comment/1 returns a comment changeset" do
+ comment = comment_fixture()
+ assert %Ecto.Changeset{} = Discussions.change_comment(comment)
+ end
+ end
+end
diff --git a/update/test/update_web/controllers/comment_controller_test.exs b/update/test/update_web/controllers/comment_controller_test.exs
new file mode 100644
index 0000000..f7c247f
--- /dev/null
+++ b/update/test/update_web/controllers/comment_controller_test.exs
@@ -0,0 +1,88 @@
+defmodule UpdateWeb.CommentControllerTest do
+ use UpdateWeb.ConnCase
+
+ alias Update.Discussions
+
+ @create_attrs %{content: "some content"}
+ @update_attrs %{content: "some updated content"}
+ @invalid_attrs %{content: nil}
+
+ def fixture(:comment) do
+ {:ok, comment} = Discussions.create_comment(@create_attrs)
+ comment
+ end
+
+ describe "index" do
+ test "lists all comments", %{conn: conn} do
+ conn = get conn, comment_path(conn, :index)
+ assert html_response(conn, 200) =~ "Listing Comments"
+ end
+ end
+
+ describe "new comment" do
+ test "renders form", %{conn: conn} do
+ conn = get conn, comment_path(conn, :new)
+ assert html_response(conn, 200) =~ "New Comment"
+ end
+ end
+
+ describe "create comment" do
+ test "redirects to show when data is valid", %{conn: conn} do
+ conn = post conn, comment_path(conn, :create), comment: @create_attrs
+
+ assert %{id: id} = redirected_params(conn)
+ assert redirected_to(conn) == comment_path(conn, :show, id)
+
+ conn = get conn, comment_path(conn, :show, id)
+ assert html_response(conn, 200) =~ "Show Comment"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn} do
+ conn = post conn, comment_path(conn, :create), comment: @invalid_attrs
+ assert html_response(conn, 200) =~ "New Comment"
+ end
+ end
+
+ describe "edit comment" do
+ setup [:create_comment]
+
+ test "renders form for editing chosen comment", %{conn: conn, comment: comment} do
+ conn = get conn, comment_path(conn, :edit, comment)
+ assert html_response(conn, 200) =~ "Edit Comment"
+ end
+ end
+
+ describe "update comment" do
+ setup [:create_comment]
+
+ test "redirects when data is valid", %{conn: conn, comment: comment} do
+ conn = put conn, comment_path(conn, :update, comment), comment: @update_attrs
+ assert redirected_to(conn) == comment_path(conn, :show, comment)
+
+ conn = get conn, comment_path(conn, :show, comment)
+ assert html_response(conn, 200) =~ "some updated content"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn, comment: comment} do
+ conn = put conn, comment_path(conn, :update, comment), comment: @invalid_attrs
+ assert html_response(conn, 200) =~ "Edit Comment"
+ end
+ end
+
+ describe "delete comment" do
+ setup [:create_comment]
+
+ test "deletes chosen comment", %{conn: conn, comment: comment} do
+ conn = delete conn, comment_path(conn, :delete, comment)
+ assert redirected_to(conn) == comment_path(conn, :index)
+ assert_error_sent 404, fn ->
+ get conn, comment_path(conn, :show, comment)
+ end
+ end
+ end
+
+ defp create_comment(_) do
+ comment = fixture(:comment)
+ {:ok, comment: comment}
+ end
+end
diff --git a/update/test/update_web/controllers/page_controller_test.exs b/update/test/update_web/controllers/page_controller_test.exs
new file mode 100644
index 0000000..37a8a89
--- /dev/null
+++ b/update/test/update_web/controllers/page_controller_test.exs
@@ -0,0 +1,8 @@
+defmodule UpdateWeb.PageControllerTest do
+ use UpdateWeb.ConnCase
+
+ test "GET /", %{conn: conn} do
+ conn = get conn, "/"
+ assert html_response(conn, 200) =~ "Welcome to Phoenix!"
+ end
+end
diff --git a/update/test/update_web/controllers/topic_controller_test.exs b/update/test/update_web/controllers/topic_controller_test.exs
new file mode 100644
index 0000000..f897f2f
--- /dev/null
+++ b/update/test/update_web/controllers/topic_controller_test.exs
@@ -0,0 +1,88 @@
+defmodule UpdateWeb.TopicControllerTest do
+ use UpdateWeb.ConnCase
+
+ alias Update.Discussions
+
+ @create_attrs %{title: "some title"}
+ @update_attrs %{title: "some updated title"}
+ @invalid_attrs %{title: nil}
+
+ def fixture(:topic) do
+ {:ok, topic} = Discussions.create_topic(@create_attrs)
+ topic
+ end
+
+ describe "index" do
+ test "lists all topics", %{conn: conn} do
+ conn = get conn, topic_path(conn, :index)
+ assert html_response(conn, 200) =~ "Listing Topics"
+ end
+ end
+
+ describe "new topic" do
+ test "renders form", %{conn: conn} do
+ conn = get conn, topic_path(conn, :new)
+ assert html_response(conn, 200) =~ "New Topic"
+ end
+ end
+
+ describe "create topic" do
+ test "redirects to show when data is valid", %{conn: conn} do
+ conn = post conn, topic_path(conn, :create), topic: @create_attrs
+
+ assert %{id: id} = redirected_params(conn)
+ assert redirected_to(conn) == topic_path(conn, :show, id)
+
+ conn = get conn, topic_path(conn, :show, id)
+ assert html_response(conn, 200) =~ "Show Topic"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn} do
+ conn = post conn, topic_path(conn, :create), topic: @invalid_attrs
+ assert html_response(conn, 200) =~ "New Topic"
+ end
+ end
+
+ describe "edit topic" do
+ setup [:create_topic]
+
+ test "renders form for editing chosen topic", %{conn: conn, topic: topic} do
+ conn = get conn, topic_path(conn, :edit, topic)
+ assert html_response(conn, 200) =~ "Edit Topic"
+ end
+ end
+
+ describe "update topic" do
+ setup [:create_topic]
+
+ test "redirects when data is valid", %{conn: conn, topic: topic} do
+ conn = put conn, topic_path(conn, :update, topic), topic: @update_attrs
+ assert redirected_to(conn) == topic_path(conn, :show, topic)
+
+ conn = get conn, topic_path(conn, :show, topic)
+ assert html_response(conn, 200) =~ "some updated title"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn, topic: topic} do
+ conn = put conn, topic_path(conn, :update, topic), topic: @invalid_attrs
+ assert html_response(conn, 200) =~ "Edit Topic"
+ end
+ end
+
+ describe "delete topic" do
+ setup [:create_topic]
+
+ test "deletes chosen topic", %{conn: conn, topic: topic} do
+ conn = delete conn, topic_path(conn, :delete, topic)
+ assert redirected_to(conn) == topic_path(conn, :index)
+ assert_error_sent 404, fn ->
+ get conn, topic_path(conn, :show, topic)
+ end
+ end
+ end
+
+ defp create_topic(_) do
+ topic = fixture(:topic)
+ {:ok, topic: topic}
+ end
+end
diff --git a/update/test/update_web/controllers/user_controller_test.exs b/update/test/update_web/controllers/user_controller_test.exs
new file mode 100644
index 0000000..6e188e6
--- /dev/null
+++ b/update/test/update_web/controllers/user_controller_test.exs
@@ -0,0 +1,88 @@
+defmodule UpdateWeb.UserControllerTest do
+ use UpdateWeb.ConnCase
+
+ alias Update.Accounts
+
+ @create_attrs %{email: "some email"}
+ @update_attrs %{email: "some updated email"}
+ @invalid_attrs %{email: nil}
+
+ def fixture(:user) do
+ {:ok, user} = Accounts.create_user(@create_attrs)
+ user
+ end
+
+ describe "index" do
+ test "lists all users", %{conn: conn} do
+ conn = get conn, user_path(conn, :index)
+ assert html_response(conn, 200) =~ "Listing Users"
+ end
+ end
+
+ describe "new user" do
+ test "renders form", %{conn: conn} do
+ conn = get conn, user_path(conn, :new)
+ assert html_response(conn, 200) =~ "New User"
+ end
+ end
+
+ describe "create user" do
+ test "redirects to show when data is valid", %{conn: conn} do
+ conn = post conn, user_path(conn, :create), user: @create_attrs
+
+ assert %{id: id} = redirected_params(conn)
+ assert redirected_to(conn) == user_path(conn, :show, id)
+
+ conn = get conn, user_path(conn, :show, id)
+ assert html_response(conn, 200) =~ "Show User"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn} do
+ conn = post conn, user_path(conn, :create), user: @invalid_attrs
+ assert html_response(conn, 200) =~ "New User"
+ end
+ end
+
+ describe "edit user" do
+ setup [:create_user]
+
+ test "renders form for editing chosen user", %{conn: conn, user: user} do
+ conn = get conn, user_path(conn, :edit, user)
+ assert html_response(conn, 200) =~ "Edit User"
+ end
+ end
+
+ describe "update user" do
+ setup [:create_user]
+
+ test "redirects when data is valid", %{conn: conn, user: user} do
+ conn = put conn, user_path(conn, :update, user), user: @update_attrs
+ assert redirected_to(conn) == user_path(conn, :show, user)
+
+ conn = get conn, user_path(conn, :show, user)
+ assert html_response(conn, 200) =~ "some updated email"
+ end
+
+ test "renders errors when data is invalid", %{conn: conn, user: user} do
+ conn = put conn, user_path(conn, :update, user), user: @invalid_attrs
+ assert html_response(conn, 200) =~ "Edit User"
+ end
+ end
+
+ describe "delete user" do
+ setup [:create_user]
+
+ test "deletes chosen user", %{conn: conn, user: user} do
+ conn = delete conn, user_path(conn, :delete, user)
+ assert redirected_to(conn) == user_path(conn, :index)
+ assert_error_sent 404, fn ->
+ get conn, user_path(conn, :show, user)
+ end
+ end
+ end
+
+ defp create_user(_) do
+ user = fixture(:user)
+ {:ok, user: user}
+ end
+end
diff --git a/update/test/update_web/views/error_view_test.exs b/update/test/update_web/views/error_view_test.exs
new file mode 100644
index 0000000..65cfe73
--- /dev/null
+++ b/update/test/update_web/views/error_view_test.exs
@@ -0,0 +1,21 @@
+defmodule UpdateWeb.ErrorViewTest do
+ use UpdateWeb.ConnCase, async: true
+
+ # Bring render/3 and render_to_string/3 for testing custom views
+ import Phoenix.View
+
+ test "renders 404.html" do
+ assert render_to_string(UpdateWeb.ErrorView, "404.html", []) ==
+ "Page not found"
+ end
+
+ test "render 500.html" do
+ assert render_to_string(UpdateWeb.ErrorView, "500.html", []) ==
+ "Internal server error"
+ end
+
+ test "render any other" do
+ assert render_to_string(UpdateWeb.ErrorView, "505.html", []) ==
+ "Internal server error"
+ end
+end
diff --git a/update/test/update_web/views/layout_view_test.exs b/update/test/update_web/views/layout_view_test.exs
new file mode 100644
index 0000000..97ad818
--- /dev/null
+++ b/update/test/update_web/views/layout_view_test.exs
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.LayoutViewTest do
+ use UpdateWeb.ConnCase, async: true
+end
diff --git a/update/test/update_web/views/page_view_test.exs b/update/test/update_web/views/page_view_test.exs
new file mode 100644
index 0000000..e2e0067
--- /dev/null
+++ b/update/test/update_web/views/page_view_test.exs
@@ -0,0 +1,3 @@
+defmodule UpdateWeb.PageViewTest do
+ use UpdateWeb.ConnCase, async: true
+end