├── LICENSE ├── README.md ├── app ├── .meteor │ ├── .finished-upgraders │ ├── .gitignore │ ├── .id │ ├── packages │ ├── platforms │ ├── release │ └── versions ├── client │ ├── collections.js │ ├── index.js │ ├── lib │ │ ├── compatibility │ │ │ ├── agency.js │ │ │ ├── agency.js~ │ │ │ ├── bootstrap.js │ │ │ ├── cbpAnimatedHeader.js │ │ │ ├── cbpAnimatedHeader.js~ │ │ │ └── classie.js~ │ │ ├── contactConfig.js │ │ ├── feedConfig.js │ │ ├── helpers │ │ │ ├── contactHelpers.js │ │ │ ├── feedHelpers.js │ │ │ ├── helperFunctions.js │ │ │ └── templateHelpers.js │ │ ├── thirdparty │ │ │ └── chance.min.js │ │ └── thirdpartyConfig.js │ ├── meta.js │ ├── routes.js │ ├── stylesheets │ │ ├── base │ │ │ ├── global.less │ │ │ ├── lib │ │ │ │ ├── bootstrap │ │ │ │ │ ├── alerts.import.less │ │ │ │ │ ├── badges.import.less │ │ │ │ │ ├── bootstrap.import.less │ │ │ │ │ ├── breadcrumbs.import.less │ │ │ │ │ ├── button-groups.import.less │ │ │ │ │ ├── buttons.import.less │ │ │ │ │ ├── carousel.import.less │ │ │ │ │ ├── close.import.less │ │ │ │ │ ├── code.import.less │ │ │ │ │ ├── component-animations.import.less │ │ │ │ │ ├── dropdowns.import.less │ │ │ │ │ ├── forms.import.less │ │ │ │ │ ├── glyphicons.import.less │ │ │ │ │ ├── grid.import.less │ │ │ │ │ ├── input-groups.import.less │ │ │ │ │ ├── jumbotron.import.less │ │ │ │ │ ├── labels.import.less │ │ │ │ │ ├── list-group.import.less │ │ │ │ │ ├── media.import.less │ │ │ │ │ ├── mixins.import.less │ │ │ │ │ ├── mixins │ │ │ │ │ │ ├── alerts.import.less │ │ │ │ │ │ ├── background-variant.import.less │ │ │ │ │ │ ├── border-radius.import.less │ │ │ │ │ │ ├── buttons.import.less │ │ │ │ │ │ ├── center-block.import.less │ │ │ │ │ │ ├── clearfix.import.less │ │ │ │ │ │ ├── forms.import.less │ │ │ │ │ │ ├── gradients.import.less │ │ │ │ │ │ ├── grid-framework.import.less │ │ │ │ │ │ ├── grid.import.less │ │ │ │ │ │ ├── hide-text.import.less │ │ │ │ │ │ ├── image.import.less │ │ │ │ │ │ ├── labels.import.less │ │ │ │ │ │ ├── list-group.import.less │ │ │ │ │ │ ├── nav-divider.import.less │ │ │ │ │ │ ├── nav-vertical-align.import.less │ │ │ │ │ │ ├── opacity.import.less │ │ │ │ │ │ ├── pagination.import.less │ │ │ │ │ │ ├── panels.import.less │ │ │ │ │ │ ├── progress-bar.import.less │ │ │ │ │ │ ├── reset-filter.import.less │ │ │ │ │ │ ├── resize.import.less │ │ │ │ │ │ ├── responsive-visibility.import.less │ │ │ │ │ │ ├── size.import.less │ │ │ │ │ │ ├── tab-focus.import.less │ │ │ │ │ │ ├── table-row.import.less │ │ │ │ │ │ ├── text-emphasis.import.less │ │ │ │ │ │ ├── text-overflow.import.less │ │ │ │ │ │ └── vendor-prefixes.import.less │ │ │ │ │ ├── modals.import.less │ │ │ │ │ ├── navbar.import.less │ │ │ │ │ ├── navs.import.less │ │ │ │ │ ├── normalize.import.less │ │ │ │ │ ├── pager.import.less │ │ │ │ │ ├── pagination.import.less │ │ │ │ │ ├── panels.import.less │ │ │ │ │ ├── popovers.import.less │ │ │ │ │ ├── print.import.less │ │ │ │ │ ├── progress-bars.import.less │ │ │ │ │ ├── responsive-embed.import.less │ │ │ │ │ ├── responsive-utilities.import.less │ │ │ │ │ ├── scaffolding.import.less │ │ │ │ │ ├── tables.import.less │ │ │ │ │ ├── theme.import.less │ │ │ │ │ ├── thumbnails.import.less │ │ │ │ │ ├── tooltip.import.less │ │ │ │ │ ├── type.import.less │ │ │ │ │ ├── utilities.import.less │ │ │ │ │ ├── variables.import.less │ │ │ │ │ └── wells.import.less │ │ │ │ └── font-awesome │ │ │ │ │ ├── animated.import.less │ │ │ │ │ ├── bordered-pulled.import.less │ │ │ │ │ ├── core.import.less │ │ │ │ │ ├── fixed-width.import.less │ │ │ │ │ ├── font-awesome.import.less │ │ │ │ │ ├── icons.import.less │ │ │ │ │ ├── larger.import.less │ │ │ │ │ ├── list.import.less │ │ │ │ │ ├── mixins.import.less │ │ │ │ │ ├── path.import.less │ │ │ │ │ ├── rotated-flipped.import.less │ │ │ │ │ ├── stacked.import.less │ │ │ │ │ └── variables.import.less │ │ │ ├── mixins.import.less │ │ │ ├── type.import.less │ │ │ └── variables.import.less │ │ └── components │ │ │ ├── buttons.import.less │ │ │ └── loading.import.less │ └── templates │ │ ├── components │ │ ├── balance.html │ │ ├── balance.js │ │ ├── checkSubscription.html │ │ ├── checkSubscription.js │ │ ├── contact.html │ │ ├── contact.js │ │ ├── dashbar.html │ │ ├── dashbar.js │ │ ├── deployment.html │ │ ├── deployment.js │ │ ├── feedInfo.html │ │ ├── feedInfo.js │ │ ├── killFeed.html │ │ ├── killFeed.js │ │ ├── subscribe.html │ │ ├── subscribe.js │ │ ├── subscriptionSettings.html │ │ └── subscriptionSettings.js │ │ ├── index.html │ │ ├── layout │ │ ├── _footer.html │ │ ├── _header.html │ │ ├── main.html │ │ └── notFound.html │ │ └── views │ │ ├── admin.html │ │ ├── admin.js │ │ ├── home.html │ │ ├── home.js │ │ ├── track.html │ │ └── track.js ├── i18n │ ├── app.en.i18n.json │ └── dapp.en.i18n.json ├── project-tap.i18n ├── public │ ├── fonts │ │ ├── font-awesome │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ └── glyphicons-halflings │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ └── images │ │ ├── about │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ ├── 3.jpg │ │ └── 4.jpg │ │ ├── coin.png │ │ ├── favicons │ │ ├── android-chrome-144x144.png │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-36x36.png │ │ ├── android-chrome-48x48.png │ │ ├── android-chrome-72x72.png │ │ ├── android-chrome-96x96.png │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon-precomposed.png │ │ ├── apple-touch-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── manifest.json │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ └── mstile-70x70.png │ │ ├── header-bg-new.jpg │ │ ├── logos │ │ ├── aetuts.jpg │ │ ├── creative-market.jpg │ │ ├── designmodo.jpg │ │ ├── envato.jpg │ │ ├── microlancer.jpg │ │ ├── themeforest.jpg │ │ └── wordpress.jpg │ │ ├── map-image.png │ │ ├── screen.jpg │ │ └── team │ │ ├── 1.jpg │ │ ├── 2.jpg │ │ └── 3.jpg └── settings.example.json ├── pricefeed.sol └── server.py /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2015 Nick Dodson. nickdodson.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # meteor-dapp-pricefeed 2 | A MeteorJS price feed DApp - for operating price feeds on Ethereum. 3 | 4 | 5 | 6 | ** Please note that this DApp is still in Alpha (still working out the bugs). 7 | 8 | ## Installation 9 | 10 | Clone this repo 11 | 12 | $ git clone http://github.com/SilentCicero/meteor-dapp-pricefeed.git 13 | 14 | Start an eth node open the http://localhost:3000 in *mist*, *mix* or *alethzero* or run a CPP node as follows: 15 | 16 | $ eth -j -b // for a mining node: $ eth -j -b -f -n no -m yes 17 | 18 | Start your app using meteor 19 | 20 | $ cd meteor-dapp-pricefeed/app 21 | $ meteor 22 | 23 | Go to http://localhost:3000/admin 24 | 25 | - click `'Deploy PriceFeed Contract'` and copy the new address 26 | 27 | Edit client/lib/feedConfig.js 28 | 29 | - change `Feed.address` to the new address 30 | 31 | Wait for mining, refresh, enjoy! 32 | 33 | ## Server Deployment 34 | 35 | Edit server.py 36 | 37 | - change vars `CONTRACT_ADDRESS` and `OWNER_ADDRESS` to the appropriate values 38 | 39 | Running the server 40 | 41 | $ cd meteor-dapp-pricefeed/app 42 | $ python server.py 43 | 44 | ## DApp Functionality 45 | - landing page 46 | - admin page (a dashboard for contract owner) 47 | - tracking page (to track subscriptions) 48 | - can subscribe an address 49 | - only subscribers can access the feed data 50 | - renewable subscriptions 51 | - owner can manage feed price, subscribers, subscription duration and payout balance 52 | - a basic python server for updating the feed info 53 | 54 | ## Page Layout 55 | - Landing page: / 56 | - Admin page: /admin 57 | - Tracking page: /track/0x00000 58 | 59 | ## About 60 | 61 | This DApp is a starting point for deploying and operating price feeds on Ethereum. It could potentially be modified to meet the needs of almost any price feed. Presently, the default title is "Gold Price Today*" (which will be my gold price feed). 62 | 63 | Original SOL by Gavin Wood 64 | 65 | ## TODO 66 | - Decimal number support for feed info 67 | - Multi-type feed data (e.g. "gold", "silver" etc.) 68 | - Better error handling 69 | - Trigger event on info update 70 | - Setup contact form (make active) 71 | -------------------------------------------------------------------------------- /app/.meteor/.finished-upgraders: -------------------------------------------------------------------------------- 1 | # This file contains information which helps Meteor properly upgrade your 2 | # app when you run 'meteor update'. You should check it into version control 3 | # with your project. 4 | 5 | notices-for-0.9.0 6 | notices-for-0.9.1 7 | 0.9.4-platform-file 8 | -------------------------------------------------------------------------------- /app/.meteor/.gitignore: -------------------------------------------------------------------------------- 1 | local 2 | -------------------------------------------------------------------------------- /app/.meteor/.id: -------------------------------------------------------------------------------- 1 | # This file contains a token that is unique to your project. 2 | # Check it into your repository along with the rest of this directory. 3 | # It can be used for purposes such as: 4 | # - ensuring you don't accidentally deploy one app on top of another 5 | # - providing package authors with aggregated statistics 6 | 7 | wzsvj5186nsct1gvqf6b 8 | -------------------------------------------------------------------------------- /app/.meteor/packages: -------------------------------------------------------------------------------- 1 | # Meteor packages used by this project, one per line. 2 | # Check this file (and the other files in this directory) into your repository. 3 | # 4 | # 'meteor add' and 'meteor remove' will edit this file for you, 5 | # but you can also edit it by hand. 6 | 7 | meteor-platform 8 | reactive-var 9 | less 10 | iron:router 11 | fastclick 12 | tap:i18n 13 | 3stack:bignumber 14 | zimme:iron-router-active 15 | yasinuslu:blaze-meta 16 | numeral:numeral 17 | ethereum:elements 18 | ethereum:tools 19 | ethereum:js 20 | frozeman:persistent-minimongo 21 | frozeman:storage 22 | frozeman:template-var 23 | frozeman:reactive-timer 24 | mrt:moment 25 | dburles:collection-helpers 26 | matb33:collection-hooks 27 | raix:handlebar-helpers 28 | chuangbo:cookie 29 | markdown -------------------------------------------------------------------------------- /app/.meteor/platforms: -------------------------------------------------------------------------------- 1 | server 2 | browser 3 | -------------------------------------------------------------------------------- /app/.meteor/release: -------------------------------------------------------------------------------- 1 | METEOR@1.0.3.2 2 | -------------------------------------------------------------------------------- /app/.meteor/versions: -------------------------------------------------------------------------------- 1 | 3stack:bignumber@2.0.0 2 | aldeed:simple-schema@1.3.0 3 | amplify@1.0.0 4 | application-configuration@1.0.4 5 | autoupdate@1.1.5 6 | base64@1.0.2 7 | binary-heap@1.0.2 8 | blaze@2.0.4 9 | blaze-tools@1.0.2 10 | boilerplate-generator@1.0.2 11 | callback-hook@1.0.2 12 | cfs:http-methods@0.0.27 13 | check@1.0.4 14 | chuangbo:cookie@1.1.0 15 | coffeescript@1.0.5 16 | dburles:collection-helpers@1.0.2 17 | ddp@1.0.14 18 | deps@1.0.6 19 | ejson@1.0.5 20 | ethereum:elements@0.1.1 21 | ethereum:js@0.1.0 22 | ethereum:tools@0.0.2 23 | fastclick@1.0.2 24 | follower-livedata@1.0.3 25 | frozeman:animation-helper@0.2.5 26 | frozeman:persistent-minimongo@0.1.3 27 | frozeman:reactive-timer@0.1.7 28 | frozeman:storage@0.1.8 29 | frozeman:template-var@1.0.5 30 | geojson-utils@1.0.2 31 | html-tools@1.0.3 32 | htmljs@1.0.3 33 | http@1.0.10 34 | id-map@1.0.2 35 | iron:controller@1.0.7 36 | iron:core@1.0.7 37 | iron:dynamic-template@1.0.7 38 | iron:layout@1.0.7 39 | iron:location@1.0.7 40 | iron:middleware-stack@1.0.7 41 | iron:router@1.0.7 42 | iron:url@1.0.7 43 | jquery@1.11.3 44 | json@1.0.2 45 | launch-screen@1.0.1 46 | less@1.0.12 47 | livedata@1.0.12 48 | localstorage@1.0.2 49 | logging@1.0.6 50 | markdown@1.0.3 51 | matb33:collection-hooks@0.7.11 52 | meteor@1.1.4 53 | meteor-platform@1.2.1 54 | minifiers@1.1.3 55 | minimongo@1.0.6 56 | mistereo:identicon@1.0.0 57 | mobile-status-bar@1.0.2 58 | mongo@1.0.11 59 | mrt:moment@2.8.1 60 | numeral:numeral@1.5.3 61 | observe-sequence@1.0.4 62 | ordered-dict@1.0.2 63 | raix:handlebar-helpers@0.2.4 64 | random@1.0.2 65 | reactive-dict@1.0.5 66 | reactive-var@1.0.4 67 | reload@1.1.2 68 | retry@1.0.2 69 | routepolicy@1.0.4 70 | session@1.0.5 71 | spacebars@1.0.5 72 | spacebars-compiler@1.0.4 73 | tap:i18n@1.4.1 74 | templating@1.0.11 75 | tracker@1.0.5 76 | ui@1.0.5 77 | underscore@1.0.2 78 | url@1.0.3 79 | webapp@1.1.6 80 | webapp-hashing@1.0.2 81 | wizonesolutions:underscore-string@1.0.0 82 | yasinuslu:blaze-meta@0.3.1 83 | zimme:iron-router-active@1.0.1 84 | -------------------------------------------------------------------------------- /app/client/collections.js: -------------------------------------------------------------------------------- 1 | 2 | // Basic (local) collections 3 | // we use {connection: null} to prevent them from syncing with our not existing Meteor server 4 | 5 | // A collection for contact messages. TODO 6 | //Messages = new Mongo.Collection('messages', {connection: null}); 7 | //new PersistentMinimongo(Messages); -------------------------------------------------------------------------------- /app/client/index.js: -------------------------------------------------------------------------------- 1 | 2 | // disconnect any meteor server 3 | if(location.host !== 'localhost:3000' && location.host !== '127.0.0.1:3000') 4 | Meteor.disconnect(); 5 | 6 | 7 | // Set the default unit to ether 8 | if(!LocalStore.get('etherUnit')) 9 | LocalStore.set('etherUnit', 'ether'); 10 | 11 | 12 | // Set Session default values for components 13 | if (Meteor.isClient) { 14 | Session.setDefault('subscribed', false); 15 | Session.setDefault('balance', 0); 16 | Session.setDefault('subscriberAddress', 0); 17 | Session.setDefault('etherUnit', LocalStore.get('etherUnit')); 18 | Session.setDefault('renewed', false); 19 | 20 | // Highlight Code TODO 21 | // hljs.initHighlightingOnLoad(); 22 | } 23 | 24 | 25 | Meteor.startup(function() { 26 | 27 | // SET default language 28 | if(Cookie.get('TAPi18next')) { 29 | TAPi18n.setLanguage(Cookie.get('TAPi18next')); 30 | } else { 31 | var userLang = navigator.language || navigator.userLanguage, 32 | availLang = TAPi18n.getLanguages(); 33 | 34 | // set default language 35 | if (_.isObject(availLang) && availLang[userLang]) { 36 | TAPi18n.setLanguage(userLang); 37 | // lang = userLang; 38 | } else if (_.isObject(availLang) && availLang[userLang.substr(0,2)]) { 39 | TAPi18n.setLanguage(userLang.substr(0,2)); 40 | // lang = userLang.substr(0,2); 41 | } else { 42 | TAPi18n.setLanguage('en'); 43 | // lang = 'en'; 44 | } 45 | } 46 | 47 | Tracker.autorun(function(){ 48 | if(_.isString(TAPi18n.getLanguage())) { 49 | moment.locale(TAPi18n.getLanguage().substr(0,2)); 50 | numeral.language(TAPi18n.getLanguage().substr(0,2)); 51 | } 52 | }); 53 | 54 | // Set Meta Title 55 | Meta.setTitle(TAPi18n.__("dapp.app.title")); 56 | }); -------------------------------------------------------------------------------- /app/client/lib/compatibility/agency.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com) 3 | * Code licensed under the Apache License v2.0. 4 | * For details, see http://www.apache.org/licenses/LICENSE-2.0. 5 | */ 6 | 7 | // jQuery for page scrolling feature - requires jQuery Easing plugin 8 | $(function() { 9 | $('a.page-scroll').bind('click', function(event) { 10 | var $anchor = $(this); 11 | $('html, body').stop().animate({ 12 | scrollTop: $($anchor.attr('href')).offset().top 13 | }, 1500, 'easeInOutExpo'); 14 | event.preventDefault(); 15 | }); 16 | }); 17 | 18 | // Highlight the top nav as scrolling occurs 19 | /*$('body').scrollspy({ 20 | target: '.navbar-fixed-top' 21 | })*/ 22 | 23 | // Closes the Responsive Menu on Menu Item Click 24 | $('.navbar-collapse ul li a').click(function() { 25 | $('.navbar-toggle:visible').click(); 26 | }); 27 | -------------------------------------------------------------------------------- /app/client/lib/compatibility/agency.js~: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com) 3 | * Code licensed under the Apache License v2.0. 4 | * For details, see http://www.apache.org/licenses/LICENSE-2.0. 5 | */ 6 | 7 | // jQuery for page scrolling feature - requires jQuery Easing plugin 8 | $(function() { 9 | $('a.page-scroll').bind('click', function(event) { 10 | var $anchor = $(this); 11 | $('html, body').stop().animate({ 12 | scrollTop: $($anchor.attr('href')).offset().top 13 | }, 1500, 'easeInOutExpo'); 14 | event.preventDefault(); 15 | }); 16 | }); 17 | 18 | // Highlight the top nav as scrolling occurs 19 | $('body').scrollspy({ 20 | target: '.navbar-fixed-top' 21 | }) 22 | 23 | // Closes the Responsive Menu on Menu Item Click 24 | $('.navbar-collapse ul li a').click(function() { 25 | $('.navbar-toggle:visible').click(); 26 | }); 27 | -------------------------------------------------------------------------------- /app/client/lib/compatibility/cbpAnimatedHeader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * cbpAnimatedHeader.js v1.0.0 3 | * http://www.codrops.com 4 | * 5 | * Licensed under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 8 | * Copyright 2013, Codrops 9 | * http://www.codrops.com 10 | */ 11 | var cbpAnimatedHeader_disable = false; 12 | var cbpAnimatedHeader = (function() { 13 | 14 | var docElem = document.documentElement, 15 | header = document.querySelector( '.navbar-default' ), 16 | didScroll = false, 17 | changeHeaderOn = 300; 18 | 19 | function init() { 20 | window.addEventListener( 'scroll', function( event ) { 21 | if( !didScroll ) { 22 | didScroll = true; 23 | setTimeout( scrollPage, 250 ); 24 | } 25 | }, false ); 26 | } 27 | 28 | function scrollPage() { 29 | if(cbpAnimatedHeader_disable == false){ 30 | var sy = scrollY(); 31 | if ( sy >= changeHeaderOn ) { 32 | $('.navbar-default').addClass( "navbar-shrink" ); 33 | //classie.add( header, 'navbar-shrink' ); 34 | } 35 | else { 36 | $('.navbar-default').removeClass( "navbar-shrink" ); 37 | //classie.remove( header, 'navbar-shrink' ); 38 | } 39 | didScroll = false; 40 | } 41 | } 42 | 43 | function scrollY() { 44 | return window.pageYOffset || docElem.scrollTop; 45 | } 46 | 47 | init(); 48 | 49 | })(); 50 | -------------------------------------------------------------------------------- /app/client/lib/compatibility/cbpAnimatedHeader.js~: -------------------------------------------------------------------------------- 1 | /** 2 | * cbpAnimatedHeader.js v1.0.0 3 | * http://www.codrops.com 4 | * 5 | * Licensed under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 8 | * Copyright 2013, Codrops 9 | * http://www.codrops.com 10 | */ 11 | var cbpAnimatedHeader = (function() { 12 | 13 | var docElem = document.documentElement, 14 | header = document.querySelector( '.navbar-default' ), 15 | didScroll = false, 16 | changeHeaderOn = 300; 17 | 18 | function init() { 19 | window.addEventListener( 'scroll', function( event ) { 20 | if( !didScroll ) { 21 | didScroll = true; 22 | setTimeout( scrollPage, 250 ); 23 | } 24 | }, false ); 25 | } 26 | 27 | function scrollPage() { 28 | var sy = scrollY(); 29 | if ( sy >= changeHeaderOn ) { 30 | $('.navbar-default').addClass( "cbp-af-header-shrink" ); 31 | //classie.add( header, 'navbar-shrink' ); 32 | } 33 | else { 34 | $('.navbar-default').removeClass( "cbp-af-header-shrink" ); 35 | //classie.remove( header, 'navbar-shrink' ); 36 | } 37 | didScroll = false; 38 | } 39 | 40 | function scrollY() { 41 | return window.pageYOffset || docElem.scrollTop; 42 | } 43 | 44 | init(); 45 | 46 | })(); 47 | -------------------------------------------------------------------------------- /app/client/lib/compatibility/classie.js~: -------------------------------------------------------------------------------- 1 | /*! 2 | * classie - class helper functions 3 | * from bonzo https://github.com/ded/bonzo 4 | * 5 | * classie.has( elem, 'my-class' ) -> true/false 6 | * classie.add( elem, 'my-new-class' ) 7 | * classie.remove( elem, 'my-unwanted-class' ) 8 | * classie.toggle( elem, 'my-class' ) 9 | */ 10 | 11 | /*jshint browser: true, strict: true, undef: true */ 12 | /*global define: false */ 13 | 14 | ( function( window ) { 15 | 16 | 'use strict'; 17 | 18 | // class helper functions from bonzo https://github.com/ded/bonzo 19 | 20 | function classReg( className ) { 21 | return new RegExp("(^|\\s+)" + className + "(\\s+|$)"); 22 | } 23 | 24 | // classList support for class management 25 | // altho to be fair, the api sucks because it won't accept multiple classes at once 26 | var hasClass, addClass, removeClass; 27 | 28 | if ( 'classList' in document.documentElement ) { 29 | hasClass = function( elem, c ) { 30 | return elem.classList.contains( c ); 31 | }; 32 | addClass = function( elem, c ) { 33 | elem.classList.add( c ); 34 | }; 35 | removeClass = function( elem, c ) { 36 | elem.classList.remove( c ); 37 | }; 38 | } 39 | else { 40 | hasClass = function( elem, c ) { 41 | return classReg( c ).test( elem.className ); 42 | }; 43 | addClass = function( elem, c ) { 44 | if ( !hasClass( elem, c ) ) { 45 | elem.className = elem.className + ' ' + c; 46 | } 47 | }; 48 | removeClass = function( elem, c ) { 49 | elem.className = elem.className.replace( classReg( c ), ' ' ); 50 | }; 51 | } 52 | 53 | function toggleClass( elem, c ) { 54 | var fn = hasClass( elem, c ) ? removeClass : addClass; 55 | fn( elem, c ); 56 | } 57 | 58 | var classie = { 59 | // full names 60 | hasClass: hasClass, 61 | addClass: addClass, 62 | removeClass: removeClass, 63 | toggleClass: toggleClass, 64 | // short names 65 | has: hasClass, 66 | add: addClass, 67 | remove: removeClass, 68 | toggle: toggleClass 69 | }; 70 | 71 | // transport 72 | if ( typeof define === 'function' && define.amd ) { 73 | // AMD 74 | define( classie ); 75 | } else { 76 | // browser global 77 | window.classie = classie; 78 | } 79 | 80 | })( window ); 81 | -------------------------------------------------------------------------------- /app/client/lib/contactConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | Contact Configuration 3 | 4 | @module Contact 5 | */ 6 | 7 | /** 8 | The contact identity of the administrator. 9 | 10 | @var (hex) 11 | **/ 12 | 13 | Contact.identity = '0x046a2b10c047cca14b6e499516e0d230ea00af7230773170fa6bf967d6d6a0ebbf66eea1919d18cd0a7596c3d0f5c99c3d9657d5938dad3b6e467c89a2ef25e92b'; 14 | 15 | /** 16 | The ttl for contact messages. 17 | 18 | @var (ttl) 19 | **/ 20 | 21 | Contact.ttl = 100; 22 | 23 | /** 24 | The workToProve amount for sending the admin a message. 25 | 26 | @var (workToProve) 27 | **/ 28 | 29 | Contact.workToProve = 100; -------------------------------------------------------------------------------- /app/client/lib/helpers/contactHelpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | The Contact helper functions, this will be used to help establish a contact form with the admins of the dapp. 3 | 4 | @class Contact 5 | @constructor 6 | */ 7 | 8 | /** 9 | The PriceFeed functions and variables. 10 | 11 | @class PriceFeed 12 | @constructor 13 | */ 14 | 15 | Contact = {}; 16 | 17 | /** 18 | Create a new contact identity. 19 | 20 | @method (newIdentity) 21 | **/ 22 | 23 | Contact.newIdentity = function(){ 24 | var identity = web3.shh.newIdentity(); 25 | console.log('New Identity', identity); 26 | return identity; 27 | }; 28 | 29 | /** 30 | Send the admins a message. 31 | 32 | @method (message) 33 | **/ 34 | 35 | Contact.message = function(from, topic, payload){ 36 | //var identity = web3.shh.newIdentity(); 37 | //var topic = 'example'; 38 | //var payload = 'hello whisper world!'; 39 | 40 | var message = { 41 | to: Contact.identity, 42 | from: from, 43 | topics: [topic], 44 | payload: payload, 45 | ttl: Contact.ttl, 46 | workToProve: Contact.workToProve // or priority TODO 47 | }; 48 | 49 | console.log('Sending message:', message); 50 | 51 | web3.shh.post(message); 52 | }; -------------------------------------------------------------------------------- /app/client/lib/helpers/feedHelpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | The PriceFeed functions and variables. 3 | 4 | @class PriceFeed 5 | @constructor 6 | */ 7 | 8 | Feed = {}; 9 | 10 | /** 11 | Feed Setup, setup the contract object 12 | 13 | @method (setup) 14 | **/ 15 | 16 | Feed.setup = function(){ 17 | var PriceFeed = web3.eth.contract(Feed.abi); 18 | Feed.contract = new PriceFeed(Feed.address); 19 | }; 20 | 21 | /** 22 | The main from address to be used for transactions and calls. 23 | 24 | @method (from) 25 | **/ 26 | 27 | Feed.from = function(){ 28 | return web3.eth.accounts[this.account]; 29 | } 30 | 31 | /** 32 | Bare minimum call params. Includes the now mandatory from param. 33 | 34 | @method (callParams) 35 | **/ 36 | 37 | Feed.callParams = function(){ 38 | return {from: this.from()}; 39 | } 40 | 41 | /** 42 | Deploy A PriceFeed Contract 43 | 44 | @method (deploy) 45 | **/ 46 | 47 | Feed.deploy = function(){ 48 | var addr = web3.eth.sendTransaction({from: this.from(), code: Feed.hex, gas: 700000, gasPrice: web3.eth.gasPrice}); // Eventually web3.eth.solidity(source) instead of hex for Go CLI 49 | console.log('New PriceFeed address: ', addr); 50 | return addr; 51 | }; 52 | 53 | /** 54 | Display the feed subscription price in Ether. 55 | 56 | @method (priceDisplay) 57 | **/ 58 | 59 | Feed.priceDisplay = function(){ 60 | return web3.fromWei(this.contract.call(this.callParams()).price(), LocalStore.get('etherUnit')).toString(10); 61 | }; 62 | 63 | /** 64 | Display the feed subscription duration in days. 65 | 66 | @method (durationDisplay) 67 | **/ 68 | 69 | Feed.durationDisplay = function(){ 70 | return parseInt(this.contract.call(this.callParams()).duration())/(24 * 60 * 60); 71 | }; 72 | 73 | /** 74 | Display the pricefeed info. 75 | 76 | @method (infoDisplay) 77 | **/ 78 | 79 | Feed.infoDisplay = function(){ 80 | console.log(this.contract.call(this.callParams()).get()); 81 | return this.contract.call({from: this.from()}).get().toString(10); 82 | }; 83 | 84 | /** 85 | Balance Display 86 | 87 | @method (balanceDisplay) 88 | **/ 89 | 90 | Feed.balanceDisplay = function(){ 91 | return web3.fromWei(this.contract.call(this.callParams()).balance(), LocalStore.get('etherUnit')).toString(10); 92 | }; 93 | 94 | /** 95 | Subscribers Display 96 | 97 | @method (subscribersDisplay) 98 | **/ 99 | 100 | Feed.subscribersDisplay = function(){ 101 | return this.contract.call(this.callParams()).numSubscribed().toString(10); 102 | }; 103 | 104 | /** 105 | Feed Subscribe 106 | 107 | @method (subscribe) 108 | **/ 109 | 110 | Feed.subscribe = function(addr){ 111 | if(web3.isAddress(addr)) { 112 | var price = this.contract.call(this.callParams()).price().toString(10); 113 | this.contract.sendTransaction({from: this.from(), value: price}).subscribe(addr); 114 | console.log('Subscribe:', {from: this.from(), value: price}, addr); 115 | }else{ 116 | console.log('Please enter a valid address.'); 117 | } 118 | }; 119 | 120 | /** 121 | Feed set info manually (should not be used, as it should really be done by a server). 122 | 123 | @method (setInfo) 124 | **/ 125 | 126 | Feed.setInfo = function(info){ 127 | this.contract.sendTransaction({from: this.from()}).set(info); 128 | console.log('Set info to: ', info); 129 | }; 130 | 131 | /** 132 | Feed Set Subscription Price 133 | 134 | @method (setPrice) 135 | **/ 136 | 137 | Feed.setPrice = function(price){ 138 | var wei_value = web3.toWei(price, LocalStore.get('etherUnit')); 139 | this.contract.sendTransaction({from: this.from()}).setPrice(wei_value); 140 | console.log('Set price to: ', price); 141 | return price; 142 | }; 143 | 144 | /** 145 | Feed Set Subscription Period 146 | 147 | @method (setPeriod) 148 | **/ 149 | 150 | Feed.setDuration = function(period){ 151 | this.contract.sendTransaction({from: this.from()}).setDuration(parseInt(period) * 24 * 60 * 60); 152 | console.log('Set period to: ', period); 153 | return period; 154 | }; 155 | 156 | /** 157 | Feed Payout 158 | 159 | @method (payout) 160 | **/ 161 | 162 | Feed.payout = function(addr){ 163 | if(web3.isAddress(addr)) { 164 | this.contract.sendTransaction({from: this.from()}).payout(addr); 165 | console.log('Payout balance to: ', addr); 166 | } 167 | }; 168 | 169 | /** 170 | Get Subscription Status/Info 171 | 172 | @method (subscription) 173 | **/ 174 | 175 | Feed.subscription = function(addr){ 176 | if(web3.isAddress(addr)) { 177 | var info = this.contract.call(this.callParams()).subscribers(addr); 178 | console.log('Subscription info: ', info.toString(10)); 179 | return info.toString(10); 180 | } 181 | }; 182 | 183 | /** 184 | Get the number of subscribers 185 | 186 | @method (numSubscribed) 187 | **/ 188 | 189 | Feed.numSubscribed = function(){ 190 | var info = this.contract.call(this.callParams()).numSubscribed(); 191 | return info.toString(10); 192 | }; 193 | 194 | /** 195 | Kill PriceFeed 196 | 197 | @method (kill) 198 | **/ 199 | 200 | Feed.kill = function(){ 201 | this.contract.sendTransaction({from: this.from()}).kill(); 202 | console.log('Killing price feed contract...'); 203 | }; 204 | -------------------------------------------------------------------------------- /app/client/lib/helpers/helperFunctions.js: -------------------------------------------------------------------------------- 1 | /** 2 | Helper functions 3 | 4 | @module Helpers 5 | **/ 6 | 7 | /** 8 | The Helpers class containing helper functions 9 | 10 | @class Helpers 11 | @constructor 12 | **/ 13 | 14 | Helpers = {}; 15 | 16 | /** 17 | Reruns functions reactively, based on an interval. Use it like so: 18 | 19 | Helpers.rerun['10s'].tick(); 20 | 21 | @method (rerun) 22 | **/ 23 | 24 | Helpers.rerun = { 25 | '10s': new ReactiveTimer(10) 26 | }; 27 | 28 | 29 | /** 30 | Clear localStorage 31 | 32 | @method (getLocalStorageSize) 33 | **/ 34 | 35 | Helpers.getLocalStorageSize = function(){ 36 | 37 | var size = 0; 38 | if(localStorage) { 39 | _.each(Object.keys(localStorage), function(key){ 40 | size += localStorage[key].length * 2 / 1024 / 1024; 41 | }); 42 | } 43 | 44 | return size; 45 | }; 46 | 47 | 48 | 49 | /** 50 | Reactive wrapper for the moment package. 51 | 52 | @method (moment) 53 | @param {String} time a date object passed to moment function. 54 | @return {Object} the moment js package 55 | **/ 56 | 57 | Helpers.moment = function(time){ 58 | 59 | // react to language changes as well 60 | TAPi18n.getLanguage(); 61 | 62 | if(_.isFinite(time) && moment.unix(time).isValid()) 63 | return moment.unix(time); 64 | else 65 | return moment(time); 66 | 67 | }; 68 | 69 | 70 | /** 71 | Formats a timestamp to any format given. 72 | 73 | Helpers.formatTime(myTime, "YYYY-MM-DD") 74 | 75 | @method (formatTime) 76 | @param {String} time The timstamp, can be string or unix format 77 | @param {String} format the format string, can also be "iso", to format to ISO string, or "fromnow" 78 | @return {String} The formated time 79 | **/ 80 | 81 | Helpers.formatTime = function(time, format) { //parameters 82 | 83 | // make sure not existing values are not Spacebars.kw 84 | if(format instanceof Spacebars.kw) 85 | format = null; 86 | 87 | if(time) { 88 | 89 | if(_.isString(format) && !_.isEmpty(format)) { 90 | 91 | if(format.toLowerCase() === 'iso') 92 | time = Helpers.moment(time).toISOString(); 93 | else if(format.toLowerCase() === 'fromnow') { 94 | // make reactive updating 95 | Helpers.rerun['10s'].tick(); 96 | time = Helpers.moment(time).fromNow(); 97 | } else 98 | time = Helpers.moment(time).format(format); 99 | } 100 | 101 | return time; 102 | 103 | } else 104 | return ''; 105 | }; 106 | -------------------------------------------------------------------------------- /app/client/lib/helpers/templateHelpers.js: -------------------------------------------------------------------------------- 1 | /** 2 | Helper functions 3 | 4 | @module Helpers 5 | **/ 6 | 7 | /** 8 | Global template helpers 9 | 10 | @class TemplateHelpers 11 | @constructor 12 | **/ 13 | 14 | /** 15 | A simple template helper to log objects in the console. 16 | 17 | @method (debug) 18 | **/ 19 | Template.registerHelper('debug', function(object){ 20 | console.log(object); 21 | }); 22 | 23 | 24 | 25 | /** 26 | Formats a timestamp to any format given. 27 | 28 | {{formatTime myTime "YYYY-MM-DD"}} 29 | 30 | @method (formatTime) 31 | @param {String} time The timstamp, can be string or unix format 32 | @param {String} format the format string, can also be "iso", to format to ISO string, or "fromnow" 33 | //@param {Boolean} realTime Whether or not this helper should re-run every 10s 34 | @return {String} The formated time 35 | **/ 36 | Template.registerHelper('formatTime', Helpers.formatTime); 37 | 38 | 39 | /** 40 | Formats a number. 41 | 42 | {{formatNumber myNumber "0,0.0[0000]"}} 43 | 44 | @method (formatNumber) 45 | @param {String} number 46 | @param {String} format the format string 47 | @return {String} The formatted number 48 | **/ 49 | Template.registerHelper('formatNumber', function(number, format){ 50 | if(format instanceof Spacebars.kw) 51 | format = null; 52 | 53 | if(number instanceof BigNumber) 54 | number = number.toNumber(); 55 | 56 | format = format || '0,0.0[0000]'; 57 | 58 | 59 | if(!_.isFinite(number)) 60 | number = numeral().unformat(number); 61 | 62 | if(_.isFinite(number)) 63 | return numeral(number).format(format); 64 | }); 65 | 66 | -------------------------------------------------------------------------------- /app/client/lib/thirdpartyConfig.js: -------------------------------------------------------------------------------- 1 | // set providor 2 | web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545/")); //8545 8080 10.10.42.116 3 | -------------------------------------------------------------------------------- /app/client/meta.js: -------------------------------------------------------------------------------- 1 | /** 2 | Template Controllers 3 | 4 | @module Meta 5 | */ 6 | 7 | /** 8 | The app meta data 9 | 10 | @class App meta 11 | @constructor 12 | */ 13 | 14 | if(Meteor.isClient) { 15 | 16 | // Meta defaults 17 | Meta.config({ 18 | options: { 19 | suffix: '' 20 | } 21 | }); 22 | 23 | 24 | /** 25 | A suffix method to allow for suffix updates (Title | [Suffix]) 26 | 27 | @method setSuffix 28 | **/ 29 | 30 | Meta.setSuffix = function(suffix){ 31 | Meta.setTitle(TAPi18n.__("dapp.app.title") + ' | ' + suffix); 32 | }; 33 | } -------------------------------------------------------------------------------- /app/client/routes.js: -------------------------------------------------------------------------------- 1 | /** 2 | Template Controllers 3 | 4 | @module Routes 5 | */ 6 | 7 | /** 8 | The app routes 9 | 10 | @class App routes 11 | @constructor 12 | */ 13 | 14 | // Change the URLS to use #! instead of real paths 15 | // Iron.Location.configure({useHashPaths: true}); 16 | 17 | // Router defaults 18 | Router.configure({ 19 | layoutTemplate: 'layout_main', 20 | notFoundTemplate: 'layout_notFound', 21 | yieldRegions: { 22 | 'layout_header': {to: 'header'} 23 | , 'layout_footer': {to: 'footer'} 24 | } 25 | }); 26 | 27 | // ROUTES 28 | 29 | /** 30 | The receive route, showing the dapp overview 31 | 32 | @route home 33 | **/ 34 | 35 | Router.route('/', { 36 | template: 'views_home', 37 | name: 'home' 38 | }); 39 | 40 | /** 41 | The admin page route. 42 | 43 | @route admin 44 | **/ 45 | 46 | Router.route('/admin', { 47 | template: 'views_admin', 48 | name: 'admin' 49 | }); 50 | 51 | /** 52 | The tracker page route, where subscriptions can be tracked. 53 | 54 | @route track 55 | **/ 56 | 57 | Router.route('/track/:_address', { 58 | template: 'views_track', 59 | name: 'track', 60 | data: function (){ 61 | _address = this.params._address; 62 | enddate_unix = Feed.subscription(_address); 63 | enddate = 'No end date'; 64 | status = 'inactive'; 65 | if(_.isUndefined(enddate_unix) || enddate_unix == 0){ 66 | enddate_unix = false; 67 | }else{ 68 | enddate = moment.unix(enddate_unix).format('LLLL'); 69 | if(enddate_unix > moment().unix()){ 70 | status = 'active'; 71 | } 72 | } 73 | templateData = { 74 | _address: _address, 75 | enddate: enddate, 76 | enddate_unix: enddate_unix, 77 | status: status 78 | }; 79 | return templateData; 80 | }, 81 | }); -------------------------------------------------------------------------------- /app/client/stylesheets/base/global.less: -------------------------------------------------------------------------------- 1 | @components: '../components'; 2 | 3 | // Bootstrap 4 | 5 | @import "./lib/bootstrap/bootstrap.import.less"; 6 | 7 | // Font Awesome 8 | 9 | @import "./lib/font-awesome/font-awesome.import.less"; 10 | 11 | // Custom Mixins, Variables and Types 12 | 13 | @import './mixins.import.less'; 14 | @import './variables.import.less'; 15 | @import './type.import.less'; 16 | 17 | // Components 18 | 19 | @import '@{components}/buttons.import.less'; 20 | @import '@{components}/loading.import.less'; -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/alerts.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Alerts 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base styles 7 | // ------------------------- 8 | 9 | .alert { 10 | padding: @alert-padding; 11 | margin-bottom: @line-height-computed; 12 | border: 1px solid transparent; 13 | border-radius: @alert-border-radius; 14 | 15 | // Headings for larger alerts 16 | h4 { 17 | margin-top: 0; 18 | // Specified for the h4 to prevent conflicts of changing @headings-color 19 | color: inherit; 20 | } 21 | 22 | // Provide class for links that match alerts 23 | .alert-link { 24 | font-weight: @alert-link-font-weight; 25 | } 26 | 27 | // Improve alignment and spacing of inner content 28 | > p, 29 | > ul { 30 | margin-bottom: 0; 31 | } 32 | 33 | > p + p { 34 | margin-top: 5px; 35 | } 36 | } 37 | 38 | // Dismissible alerts 39 | // 40 | // Expand the right padding and account for the close button's positioning. 41 | 42 | .alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0. 43 | .alert-dismissible { 44 | padding-right: (@alert-padding + 20); 45 | 46 | // Adjust close link position 47 | .close { 48 | position: relative; 49 | top: -2px; 50 | right: -21px; 51 | color: inherit; 52 | } 53 | } 54 | 55 | // Alternate styles 56 | // 57 | // Generate contextual modifier classes for colorizing the alert. 58 | 59 | .alert-success { 60 | .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); 61 | } 62 | 63 | .alert-info { 64 | .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); 65 | } 66 | 67 | .alert-warning { 68 | .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); 69 | } 70 | 71 | .alert-danger { 72 | .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); 73 | } 74 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/badges.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Badges 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | .badge { 8 | display: inline-block; 9 | min-width: 10px; 10 | padding: 3px 7px; 11 | font-size: @font-size-small; 12 | font-weight: @badge-font-weight; 13 | color: @badge-color; 14 | line-height: @badge-line-height; 15 | vertical-align: baseline; 16 | white-space: nowrap; 17 | text-align: center; 18 | background-color: @badge-bg; 19 | border-radius: @badge-border-radius; 20 | 21 | // Empty badges collapse automatically (not available in IE8) 22 | &:empty { 23 | display: none; 24 | } 25 | 26 | // Quick fix for badges in buttons 27 | .btn & { 28 | position: relative; 29 | top: -1px; 30 | } 31 | 32 | .btn-xs &, 33 | .btn-group-xs > .btn & { 34 | top: 0; 35 | padding: 1px 5px; 36 | } 37 | 38 | // Hover state, but only for links 39 | a& { 40 | &:hover, 41 | &:focus { 42 | color: @badge-link-hover-color; 43 | text-decoration: none; 44 | cursor: pointer; 45 | } 46 | } 47 | 48 | // Account for badges in navs 49 | .list-group-item.active > &, 50 | .nav-pills > .active > a > & { 51 | color: @badge-active-color; 52 | background-color: @badge-active-bg; 53 | } 54 | 55 | .list-group-item > & { 56 | float: right; 57 | } 58 | 59 | .list-group-item > & + & { 60 | margin-right: 5px; 61 | } 62 | 63 | .nav-pills > li > a > & { 64 | margin-left: 3px; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/bootstrap.import.less: -------------------------------------------------------------------------------- 1 | // Core variables and mixins 2 | @import "variables.import.less"; 3 | @import "mixins.import.less"; 4 | 5 | // Reset and dependencies 6 | @import "normalize.import.less"; 7 | @import "print.import.less"; 8 | @import "glyphicons.import.less"; 9 | 10 | // Core CSS 11 | @import "scaffolding.import.less"; 12 | @import "type.import.less"; 13 | @import "code.import.less"; 14 | @import "grid.import.less"; 15 | @import "tables.import.less"; 16 | @import "forms.import.less"; 17 | @import "buttons.import.less"; 18 | 19 | // Components 20 | @import "component-animations.import.less"; 21 | @import "dropdowns.import.less"; 22 | @import "button-groups.import.less"; 23 | @import "input-groups.import.less"; 24 | @import "navs.import.less"; 25 | @import "navbar.import.less"; 26 | @import "breadcrumbs.import.less"; 27 | @import "pagination.import.less"; 28 | @import "pager.import.less"; 29 | @import "labels.import.less"; 30 | @import "badges.import.less"; 31 | @import "jumbotron.import.less"; 32 | @import "thumbnails.import.less"; 33 | @import "alerts.import.less"; 34 | @import "progress-bars.import.less"; 35 | @import "media.import.less"; 36 | @import "list-group.import.less"; 37 | @import "panels.import.less"; 38 | @import "responsive-embed.import.less"; 39 | @import "wells.import.less"; 40 | @import "close.import.less"; 41 | 42 | // Components w/ JavaScript 43 | @import "modals.import.less"; 44 | @import "tooltip.import.less"; 45 | @import "popovers.import.less"; 46 | @import "carousel.import.less"; 47 | 48 | // Utility classes 49 | @import "utilities.import.less"; 50 | @import "responsive-utilities.import.less"; 51 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/breadcrumbs.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Breadcrumbs 3 | // -------------------------------------------------- 4 | 5 | 6 | .breadcrumb { 7 | padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal; 8 | margin-bottom: @line-height-computed; 9 | list-style: none; 10 | background-color: @breadcrumb-bg; 11 | border-radius: @border-radius-base; 12 | 13 | > li { 14 | display: inline-block; 15 | 16 | + li:before { 17 | content: "@{breadcrumb-separator}\00a0"; // Unicode space added since inline-block means non-collapsing white-space 18 | padding: 0 5px; 19 | color: @breadcrumb-color; 20 | } 21 | } 22 | 23 | > .active { 24 | color: @breadcrumb-active-color; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/buttons.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Buttons 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base styles 7 | // -------------------------------------------------- 8 | 9 | .btn { 10 | display: inline-block; 11 | margin-bottom: 0; // For input.btn 12 | font-weight: @btn-font-weight; 13 | text-align: center; 14 | vertical-align: middle; 15 | touch-action: manipulation; 16 | cursor: pointer; 17 | background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 18 | border: 1px solid transparent; 19 | white-space: nowrap; 20 | .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base); 21 | .user-select(none); 22 | 23 | &, 24 | &:active, 25 | &.active { 26 | &:focus, 27 | &.focus { 28 | .tab-focus(); 29 | } 30 | } 31 | 32 | &:hover, 33 | &:focus, 34 | &.focus { 35 | color: @btn-default-color; 36 | text-decoration: none; 37 | } 38 | 39 | &:active, 40 | &.active { 41 | outline: 0; 42 | background-image: none; 43 | .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); 44 | } 45 | 46 | &.disabled, 47 | &[disabled], 48 | fieldset[disabled] & { 49 | cursor: @cursor-disabled; 50 | pointer-events: none; // Future-proof disabling of clicks 51 | .opacity(.65); 52 | .box-shadow(none); 53 | } 54 | } 55 | 56 | 57 | // Alternate buttons 58 | // -------------------------------------------------- 59 | 60 | .btn-default { 61 | .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border); 62 | } 63 | .btn-primary { 64 | .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border); 65 | } 66 | // Success appears as green 67 | .btn-success { 68 | .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border); 69 | } 70 | // Info appears as blue-green 71 | .btn-info { 72 | .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border); 73 | } 74 | // Warning appears as orange 75 | .btn-warning { 76 | .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border); 77 | } 78 | // Danger and error appear as red 79 | .btn-danger { 80 | .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border); 81 | } 82 | 83 | 84 | // Link buttons 85 | // ------------------------- 86 | 87 | // Make a button look and behave like a link 88 | .btn-link { 89 | color: @link-color; 90 | font-weight: normal; 91 | border-radius: 0; 92 | 93 | &, 94 | &:active, 95 | &.active, 96 | &[disabled], 97 | fieldset[disabled] & { 98 | background-color: transparent; 99 | .box-shadow(none); 100 | } 101 | &, 102 | &:hover, 103 | &:focus, 104 | &:active { 105 | border-color: transparent; 106 | } 107 | &:hover, 108 | &:focus { 109 | color: @link-hover-color; 110 | text-decoration: @link-hover-decoration; 111 | background-color: transparent; 112 | } 113 | &[disabled], 114 | fieldset[disabled] & { 115 | &:hover, 116 | &:focus { 117 | color: @btn-link-disabled-color; 118 | text-decoration: none; 119 | } 120 | } 121 | } 122 | 123 | 124 | // Button Sizes 125 | // -------------------------------------------------- 126 | 127 | .btn-lg { 128 | // line-height: ensure even-numbered height of button next to large input 129 | .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); 130 | } 131 | .btn-sm { 132 | // line-height: ensure proper height of button next to small input 133 | .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); 134 | } 135 | .btn-xs { 136 | .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small); 137 | } 138 | 139 | 140 | // Block button 141 | // -------------------------------------------------- 142 | 143 | .btn-block { 144 | display: block; 145 | width: 100%; 146 | } 147 | 148 | // Vertically space out multiple block buttons 149 | .btn-block + .btn-block { 150 | margin-top: 5px; 151 | } 152 | 153 | // Specificity overrides 154 | input[type="submit"], 155 | input[type="reset"], 156 | input[type="button"] { 157 | &.btn-block { 158 | width: 100%; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/carousel.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Carousel 3 | // -------------------------------------------------- 4 | 5 | 6 | // Wrapper for the slide container and indicators 7 | .carousel { 8 | position: relative; 9 | } 10 | 11 | .carousel-inner { 12 | position: relative; 13 | overflow: hidden; 14 | width: 100%; 15 | 16 | > .item { 17 | display: none; 18 | position: relative; 19 | .transition(.6s ease-in-out left); 20 | 21 | // Account for jankitude on images 22 | > img, 23 | > a > img { 24 | &:extend(.img-responsive); 25 | line-height: 1; 26 | } 27 | 28 | // WebKit CSS3 transforms for supported devices 29 | @media all and (transform-3d), (-webkit-transform-3d) { 30 | .transition-transform(~'0.6s ease-in-out'); 31 | .backface-visibility(~'hidden'); 32 | .perspective(1000); 33 | 34 | &.next, 35 | &.active.right { 36 | .translate3d(100%, 0, 0); 37 | left: 0; 38 | } 39 | &.prev, 40 | &.active.left { 41 | .translate3d(-100%, 0, 0); 42 | left: 0; 43 | } 44 | &.next.left, 45 | &.prev.right, 46 | &.active { 47 | .translate3d(0, 0, 0); 48 | left: 0; 49 | } 50 | } 51 | } 52 | 53 | > .active, 54 | > .next, 55 | > .prev { 56 | display: block; 57 | } 58 | 59 | > .active { 60 | left: 0; 61 | } 62 | 63 | > .next, 64 | > .prev { 65 | position: absolute; 66 | top: 0; 67 | width: 100%; 68 | } 69 | 70 | > .next { 71 | left: 100%; 72 | } 73 | > .prev { 74 | left: -100%; 75 | } 76 | > .next.left, 77 | > .prev.right { 78 | left: 0; 79 | } 80 | 81 | > .active.left { 82 | left: -100%; 83 | } 84 | > .active.right { 85 | left: 100%; 86 | } 87 | 88 | } 89 | 90 | // Left/right controls for nav 91 | // --------------------------- 92 | 93 | .carousel-control { 94 | position: absolute; 95 | top: 0; 96 | left: 0; 97 | bottom: 0; 98 | width: @carousel-control-width; 99 | .opacity(@carousel-control-opacity); 100 | font-size: @carousel-control-font-size; 101 | color: @carousel-control-color; 102 | text-align: center; 103 | text-shadow: @carousel-text-shadow; 104 | // We can't have this transition here because WebKit cancels the carousel 105 | // animation if you trip this while in the middle of another animation. 106 | 107 | // Set gradients for backgrounds 108 | &.left { 109 | #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001)); 110 | } 111 | &.right { 112 | left: auto; 113 | right: 0; 114 | #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5)); 115 | } 116 | 117 | // Hover/focus state 118 | &:hover, 119 | &:focus { 120 | outline: 0; 121 | color: @carousel-control-color; 122 | text-decoration: none; 123 | .opacity(.9); 124 | } 125 | 126 | // Toggles 127 | .icon-prev, 128 | .icon-next, 129 | .glyphicon-chevron-left, 130 | .glyphicon-chevron-right { 131 | position: absolute; 132 | top: 50%; 133 | z-index: 5; 134 | display: inline-block; 135 | } 136 | .icon-prev, 137 | .glyphicon-chevron-left { 138 | left: 50%; 139 | margin-left: -10px; 140 | } 141 | .icon-next, 142 | .glyphicon-chevron-right { 143 | right: 50%; 144 | margin-right: -10px; 145 | } 146 | .icon-prev, 147 | .icon-next { 148 | width: 20px; 149 | height: 20px; 150 | margin-top: -10px; 151 | line-height: 1; 152 | font-family: serif; 153 | } 154 | 155 | 156 | .icon-prev { 157 | &:before { 158 | content: '\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039) 159 | } 160 | } 161 | .icon-next { 162 | &:before { 163 | content: '\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A) 164 | } 165 | } 166 | } 167 | 168 | // Optional indicator pips 169 | // 170 | // Add an unordered list with the following class and add a list item for each 171 | // slide your carousel holds. 172 | 173 | .carousel-indicators { 174 | position: absolute; 175 | bottom: 10px; 176 | left: 50%; 177 | z-index: 15; 178 | width: 60%; 179 | margin-left: -30%; 180 | padding-left: 0; 181 | list-style: none; 182 | text-align: center; 183 | 184 | li { 185 | display: inline-block; 186 | width: 10px; 187 | height: 10px; 188 | margin: 1px; 189 | text-indent: -999px; 190 | border: 1px solid @carousel-indicator-border-color; 191 | border-radius: 10px; 192 | cursor: pointer; 193 | 194 | // IE8-9 hack for event handling 195 | // 196 | // Internet Explorer 8-9 does not support clicks on elements without a set 197 | // `background-color`. We cannot use `filter` since that's not viewed as a 198 | // background color by the browser. Thus, a hack is needed. 199 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer 200 | // 201 | // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we 202 | // set alpha transparency for the best results possible. 203 | background-color: #000 \9; // IE8 204 | background-color: rgba(0,0,0,0); // IE9 205 | } 206 | .active { 207 | margin: 0; 208 | width: 12px; 209 | height: 12px; 210 | background-color: @carousel-indicator-active-bg; 211 | } 212 | } 213 | 214 | // Optional captions 215 | // ----------------------------- 216 | // Hidden by default for smaller viewports 217 | .carousel-caption { 218 | position: absolute; 219 | left: 15%; 220 | right: 15%; 221 | bottom: 20px; 222 | z-index: 10; 223 | padding-top: 20px; 224 | padding-bottom: 20px; 225 | color: @carousel-caption-color; 226 | text-align: center; 227 | text-shadow: @carousel-text-shadow; 228 | & .btn { 229 | text-shadow: none; // No shadow for button elements in carousel-caption 230 | } 231 | } 232 | 233 | 234 | // Scale up controls for tablets and up 235 | @media screen and (min-width: @screen-sm-min) { 236 | 237 | // Scale up the controls a smidge 238 | .carousel-control { 239 | .glyphicon-chevron-left, 240 | .glyphicon-chevron-right, 241 | .icon-prev, 242 | .icon-next { 243 | width: 30px; 244 | height: 30px; 245 | margin-top: -15px; 246 | font-size: 30px; 247 | } 248 | .glyphicon-chevron-left, 249 | .icon-prev { 250 | margin-left: -15px; 251 | } 252 | .glyphicon-chevron-right, 253 | .icon-next { 254 | margin-right: -15px; 255 | } 256 | } 257 | 258 | // Show and left align the captions 259 | .carousel-caption { 260 | left: 20%; 261 | right: 20%; 262 | padding-bottom: 30px; 263 | } 264 | 265 | // Move up the indicators 266 | .carousel-indicators { 267 | bottom: 20px; 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/close.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Close icons 3 | // -------------------------------------------------- 4 | 5 | 6 | .close { 7 | float: right; 8 | font-size: (@font-size-base * 1.5); 9 | font-weight: @close-font-weight; 10 | line-height: 1; 11 | color: @close-color; 12 | text-shadow: @close-text-shadow; 13 | .opacity(.2); 14 | 15 | &:hover, 16 | &:focus { 17 | color: @close-color; 18 | text-decoration: none; 19 | cursor: pointer; 20 | .opacity(.5); 21 | } 22 | 23 | // Additional properties for button version 24 | // iOS requires the button element instead of an anchor tag. 25 | // If you want the anchor version, it requires `href="#"`. 26 | // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile 27 | button& { 28 | padding: 0; 29 | cursor: pointer; 30 | background: transparent; 31 | border: 0; 32 | -webkit-appearance: none; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/code.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Code (inline and block) 3 | // -------------------------------------------------- 4 | 5 | 6 | // Inline and block code styles 7 | code, 8 | kbd, 9 | pre, 10 | samp { 11 | font-family: @font-family-monospace; 12 | } 13 | 14 | // Inline code 15 | code { 16 | padding: 2px 4px; 17 | font-size: 90%; 18 | color: @code-color; 19 | background-color: @code-bg; 20 | border-radius: @border-radius-base; 21 | } 22 | 23 | // User input typically entered via keyboard 24 | kbd { 25 | padding: 2px 4px; 26 | font-size: 90%; 27 | color: @kbd-color; 28 | background-color: @kbd-bg; 29 | border-radius: @border-radius-small; 30 | box-shadow: inset 0 -1px 0 rgba(0,0,0,.25); 31 | 32 | kbd { 33 | padding: 0; 34 | font-size: 100%; 35 | font-weight: bold; 36 | box-shadow: none; 37 | } 38 | } 39 | 40 | // Blocks of code 41 | pre { 42 | display: block; 43 | padding: ((@line-height-computed - 1) / 2); 44 | margin: 0 0 (@line-height-computed / 2); 45 | font-size: (@font-size-base - 1); // 14px to 13px 46 | line-height: @line-height-base; 47 | word-break: break-all; 48 | word-wrap: break-word; 49 | color: @pre-color; 50 | background-color: @pre-bg; 51 | border: 1px solid @pre-border-color; 52 | border-radius: @border-radius-base; 53 | 54 | // Account for some code outputs that place code tags in pre tags 55 | code { 56 | padding: 0; 57 | font-size: inherit; 58 | color: inherit; 59 | white-space: pre-wrap; 60 | background-color: transparent; 61 | border-radius: 0; 62 | } 63 | } 64 | 65 | // Enable scrollable blocks of code 66 | .pre-scrollable { 67 | max-height: @pre-scrollable-max-height; 68 | overflow-y: scroll; 69 | } 70 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/component-animations.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Component animations 3 | // -------------------------------------------------- 4 | 5 | // Heads up! 6 | // 7 | // We don't use the `.opacity()` mixin here since it causes a bug with text 8 | // fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552. 9 | 10 | .fade { 11 | opacity: 0; 12 | .transition(opacity .15s linear); 13 | &.in { 14 | opacity: 1; 15 | } 16 | } 17 | 18 | .collapse { 19 | display: none; 20 | visibility: hidden; 21 | 22 | &.in { display: block; visibility: visible; } 23 | tr&.in { display: table-row; } 24 | tbody&.in { display: table-row-group; } 25 | } 26 | 27 | .collapsing { 28 | position: relative; 29 | height: 0; 30 | overflow: hidden; 31 | .transition-property(~"height, visibility"); 32 | .transition-duration(.35s); 33 | .transition-timing-function(ease); 34 | } 35 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/dropdowns.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Dropdown menus 3 | // -------------------------------------------------- 4 | 5 | 6 | // Dropdown arrow/caret 7 | .caret { 8 | display: inline-block; 9 | width: 0; 10 | height: 0; 11 | margin-left: 2px; 12 | vertical-align: middle; 13 | border-top: @caret-width-base dashed; 14 | border-right: @caret-width-base solid transparent; 15 | border-left: @caret-width-base solid transparent; 16 | } 17 | 18 | // The dropdown wrapper (div) 19 | .dropup, 20 | .dropdown { 21 | position: relative; 22 | } 23 | 24 | // Prevent the focus on the dropdown toggle when closing dropdowns 25 | .dropdown-toggle:focus { 26 | outline: 0; 27 | } 28 | 29 | // The dropdown menu (ul) 30 | .dropdown-menu { 31 | position: absolute; 32 | top: 100%; 33 | left: 0; 34 | z-index: @zindex-dropdown; 35 | display: none; // none by default, but block on "open" of the menu 36 | float: left; 37 | min-width: 160px; 38 | padding: 5px 0; 39 | margin: 2px 0 0; // override default ul 40 | list-style: none; 41 | font-size: @font-size-base; 42 | text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) 43 | background-color: @dropdown-bg; 44 | border: 1px solid @dropdown-fallback-border; // IE8 fallback 45 | border: 1px solid @dropdown-border; 46 | border-radius: @border-radius-base; 47 | .box-shadow(0 6px 12px rgba(0,0,0,.175)); 48 | background-clip: padding-box; 49 | 50 | // Aligns the dropdown menu to right 51 | // 52 | // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]` 53 | &.pull-right { 54 | right: 0; 55 | left: auto; 56 | } 57 | 58 | // Dividers (basically an hr) within the dropdown 59 | .divider { 60 | .nav-divider(@dropdown-divider-bg); 61 | } 62 | 63 | // Links within the dropdown menu 64 | > li > a { 65 | display: block; 66 | padding: 3px 20px; 67 | clear: both; 68 | font-weight: normal; 69 | line-height: @line-height-base; 70 | color: @dropdown-link-color; 71 | white-space: nowrap; // prevent links from randomly breaking onto new lines 72 | } 73 | } 74 | 75 | // Hover/Focus state 76 | .dropdown-menu > li > a { 77 | &:hover, 78 | &:focus { 79 | text-decoration: none; 80 | color: @dropdown-link-hover-color; 81 | background-color: @dropdown-link-hover-bg; 82 | } 83 | } 84 | 85 | // Active state 86 | .dropdown-menu > .active > a { 87 | &, 88 | &:hover, 89 | &:focus { 90 | color: @dropdown-link-active-color; 91 | text-decoration: none; 92 | outline: 0; 93 | background-color: @dropdown-link-active-bg; 94 | } 95 | } 96 | 97 | // Disabled state 98 | // 99 | // Gray out text and ensure the hover/focus state remains gray 100 | 101 | .dropdown-menu > .disabled > a { 102 | &, 103 | &:hover, 104 | &:focus { 105 | color: @dropdown-link-disabled-color; 106 | } 107 | 108 | // Nuke hover/focus effects 109 | &:hover, 110 | &:focus { 111 | text-decoration: none; 112 | background-color: transparent; 113 | background-image: none; // Remove CSS gradient 114 | .reset-filter(); 115 | cursor: @cursor-disabled; 116 | } 117 | } 118 | 119 | // Open state for the dropdown 120 | .open { 121 | // Show the menu 122 | > .dropdown-menu { 123 | display: block; 124 | } 125 | 126 | // Remove the outline when :focus is triggered 127 | > a { 128 | outline: 0; 129 | } 130 | } 131 | 132 | // Menu positioning 133 | // 134 | // Add extra class to `.dropdown-menu` to flip the alignment of the dropdown 135 | // menu with the parent. 136 | .dropdown-menu-right { 137 | left: auto; // Reset the default from `.dropdown-menu` 138 | right: 0; 139 | } 140 | // With v3, we enabled auto-flipping if you have a dropdown within a right 141 | // aligned nav component. To enable the undoing of that, we provide an override 142 | // to restore the default dropdown menu alignment. 143 | // 144 | // This is only for left-aligning a dropdown menu within a `.navbar-right` or 145 | // `.pull-right` nav component. 146 | .dropdown-menu-left { 147 | left: 0; 148 | right: auto; 149 | } 150 | 151 | // Dropdown section headers 152 | .dropdown-header { 153 | display: block; 154 | padding: 3px 20px; 155 | font-size: @font-size-small; 156 | line-height: @line-height-base; 157 | color: @dropdown-header-color; 158 | white-space: nowrap; // as with > li > a 159 | } 160 | 161 | // Backdrop to catch body clicks on mobile, etc. 162 | .dropdown-backdrop { 163 | position: fixed; 164 | left: 0; 165 | right: 0; 166 | bottom: 0; 167 | top: 0; 168 | z-index: (@zindex-dropdown - 10); 169 | } 170 | 171 | // Right aligned dropdowns 172 | .pull-right > .dropdown-menu { 173 | right: 0; 174 | left: auto; 175 | } 176 | 177 | // Allow for dropdowns to go bottom up (aka, dropup-menu) 178 | // 179 | // Just add .dropup after the standard .dropdown class and you're set, bro. 180 | // TODO: abstract this so that the navbar fixed styles are not placed here? 181 | 182 | .dropup, 183 | .navbar-fixed-bottom .dropdown { 184 | // Reverse the caret 185 | .caret { 186 | border-top: 0; 187 | border-bottom: @caret-width-base solid; 188 | content: ""; 189 | } 190 | // Different positioning for bottom up menu 191 | .dropdown-menu { 192 | top: auto; 193 | bottom: 100%; 194 | margin-bottom: 2px; 195 | } 196 | } 197 | 198 | 199 | // Component alignment 200 | // 201 | // Reiterate per navbar.less and the modified component alignment there. 202 | 203 | @media (min-width: @grid-float-breakpoint) { 204 | .navbar-right { 205 | .dropdown-menu { 206 | .dropdown-menu-right(); 207 | } 208 | // Necessary for overrides of the default right aligned menu. 209 | // Will remove come v4 in all likelihood. 210 | .dropdown-menu-left { 211 | .dropdown-menu-left(); 212 | } 213 | } 214 | } 215 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/grid.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Grid system 3 | // -------------------------------------------------- 4 | 5 | 6 | // Container widths 7 | // 8 | // Set the container width, and override it for fixed navbars in media queries. 9 | 10 | .container { 11 | .container-fixed(); 12 | 13 | @media (min-width: @screen-sm-min) { 14 | width: @container-sm; 15 | } 16 | @media (min-width: @screen-md-min) { 17 | width: @container-md; 18 | } 19 | @media (min-width: @screen-lg-min) { 20 | width: @container-lg; 21 | } 22 | } 23 | 24 | 25 | // Fluid container 26 | // 27 | // Utilizes the mixin meant for fixed width containers, but without any defined 28 | // width for fluid, full width layouts. 29 | 30 | .container-fluid { 31 | .container-fixed(); 32 | } 33 | 34 | 35 | // Row 36 | // 37 | // Rows contain and clear the floats of your columns. 38 | 39 | .row { 40 | .make-row(); 41 | } 42 | 43 | 44 | // Columns 45 | // 46 | // Common styles for small and large grid columns 47 | 48 | .make-grid-columns(); 49 | 50 | 51 | // Extra small grid 52 | // 53 | // Columns, offsets, pushes, and pulls for extra small devices like 54 | // smartphones. 55 | 56 | .make-grid(xs); 57 | 58 | 59 | // Small grid 60 | // 61 | // Columns, offsets, pushes, and pulls for the small device range, from phones 62 | // to tablets. 63 | 64 | @media (min-width: @screen-sm-min) { 65 | .make-grid(sm); 66 | } 67 | 68 | 69 | // Medium grid 70 | // 71 | // Columns, offsets, pushes, and pulls for the desktop device range. 72 | 73 | @media (min-width: @screen-md-min) { 74 | .make-grid(md); 75 | } 76 | 77 | 78 | // Large grid 79 | // 80 | // Columns, offsets, pushes, and pulls for the large desktop device range. 81 | 82 | @media (min-width: @screen-lg-min) { 83 | .make-grid(lg); 84 | } 85 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/input-groups.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Input groups 3 | // -------------------------------------------------- 4 | 5 | // Base styles 6 | // ------------------------- 7 | .input-group { 8 | position: relative; // For dropdowns 9 | display: table; 10 | border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table 11 | 12 | // Undo padding and float of grid classes 13 | &[class*="col-"] { 14 | float: none; 15 | padding-left: 0; 16 | padding-right: 0; 17 | } 18 | 19 | .form-control { 20 | // Ensure that the input is always above the *appended* addon button for 21 | // proper border colors. 22 | position: relative; 23 | z-index: 2; 24 | 25 | // IE9 fubars the placeholder attribute in text inputs and the arrows on 26 | // select elements in input groups. To fix it, we float the input. Details: 27 | // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855 28 | float: left; 29 | 30 | width: 100%; 31 | margin-bottom: 0; 32 | } 33 | } 34 | 35 | // Sizing options 36 | // 37 | // Remix the default form control sizing classes into new ones for easier 38 | // manipulation. 39 | 40 | .input-group-lg > .form-control, 41 | .input-group-lg > .input-group-addon, 42 | .input-group-lg > .input-group-btn > .btn { 43 | .input-lg(); 44 | } 45 | .input-group-sm > .form-control, 46 | .input-group-sm > .input-group-addon, 47 | .input-group-sm > .input-group-btn > .btn { 48 | .input-sm(); 49 | } 50 | 51 | 52 | // Display as table-cell 53 | // ------------------------- 54 | .input-group-addon, 55 | .input-group-btn, 56 | .input-group .form-control { 57 | display: table-cell; 58 | 59 | &:not(:first-child):not(:last-child) { 60 | border-radius: 0; 61 | } 62 | } 63 | // Addon and addon wrapper for buttons 64 | .input-group-addon, 65 | .input-group-btn { 66 | width: 1%; 67 | white-space: nowrap; 68 | vertical-align: middle; // Match the inputs 69 | } 70 | 71 | // Text input groups 72 | // ------------------------- 73 | .input-group-addon { 74 | padding: @padding-base-vertical @padding-base-horizontal; 75 | font-size: @font-size-base; 76 | font-weight: normal; 77 | line-height: 1; 78 | color: @input-color; 79 | text-align: center; 80 | background-color: @input-group-addon-bg; 81 | border: 1px solid @input-group-addon-border-color; 82 | border-radius: @border-radius-base; 83 | 84 | // Sizing 85 | &.input-sm { 86 | padding: @padding-small-vertical @padding-small-horizontal; 87 | font-size: @font-size-small; 88 | border-radius: @border-radius-small; 89 | } 90 | &.input-lg { 91 | padding: @padding-large-vertical @padding-large-horizontal; 92 | font-size: @font-size-large; 93 | border-radius: @border-radius-large; 94 | } 95 | 96 | // Nuke default margins from checkboxes and radios to vertically center within. 97 | input[type="radio"], 98 | input[type="checkbox"] { 99 | margin-top: 0; 100 | } 101 | } 102 | 103 | // Reset rounded corners 104 | .input-group .form-control:first-child, 105 | .input-group-addon:first-child, 106 | .input-group-btn:first-child > .btn, 107 | .input-group-btn:first-child > .btn-group > .btn, 108 | .input-group-btn:first-child > .dropdown-toggle, 109 | .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), 110 | .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { 111 | .border-right-radius(0); 112 | } 113 | .input-group-addon:first-child { 114 | border-right: 0; 115 | } 116 | .input-group .form-control:last-child, 117 | .input-group-addon:last-child, 118 | .input-group-btn:last-child > .btn, 119 | .input-group-btn:last-child > .btn-group > .btn, 120 | .input-group-btn:last-child > .dropdown-toggle, 121 | .input-group-btn:first-child > .btn:not(:first-child), 122 | .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { 123 | .border-left-radius(0); 124 | } 125 | .input-group-addon:last-child { 126 | border-left: 0; 127 | } 128 | 129 | // Button input groups 130 | // ------------------------- 131 | .input-group-btn { 132 | position: relative; 133 | // Jankily prevent input button groups from wrapping with `white-space` and 134 | // `font-size` in combination with `inline-block` on buttons. 135 | font-size: 0; 136 | white-space: nowrap; 137 | 138 | // Negative margin for spacing, position for bringing hovered/focused/actived 139 | // element above the siblings. 140 | > .btn { 141 | position: relative; 142 | + .btn { 143 | margin-left: -1px; 144 | } 145 | // Bring the "active" button to the front 146 | &:hover, 147 | &:focus, 148 | &:active { 149 | z-index: 2; 150 | } 151 | } 152 | 153 | // Negative margin to only have a 1px border between the two 154 | &:first-child { 155 | > .btn, 156 | > .btn-group { 157 | margin-right: -1px; 158 | } 159 | } 160 | &:last-child { 161 | > .btn, 162 | > .btn-group { 163 | margin-left: -1px; 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/jumbotron.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Jumbotron 3 | // -------------------------------------------------- 4 | 5 | 6 | .jumbotron { 7 | padding: @jumbotron-padding (@jumbotron-padding / 2); 8 | margin-bottom: @jumbotron-padding; 9 | color: @jumbotron-color; 10 | background-color: @jumbotron-bg; 11 | 12 | h1, 13 | .h1 { 14 | color: @jumbotron-heading-color; 15 | } 16 | 17 | p { 18 | margin-bottom: (@jumbotron-padding / 2); 19 | font-size: @jumbotron-font-size; 20 | font-weight: 200; 21 | } 22 | 23 | > hr { 24 | border-top-color: darken(@jumbotron-bg, 10%); 25 | } 26 | 27 | .container &, 28 | .container-fluid & { 29 | border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container 30 | } 31 | 32 | .container { 33 | max-width: 100%; 34 | } 35 | 36 | @media screen and (min-width: @screen-sm-min) { 37 | padding: (@jumbotron-padding * 1.6) 0; 38 | 39 | .container &, 40 | .container-fluid & { 41 | padding-left: (@jumbotron-padding * 2); 42 | padding-right: (@jumbotron-padding * 2); 43 | } 44 | 45 | h1, 46 | .h1 { 47 | font-size: (@font-size-base * 4.5); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/labels.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // Labels 3 | // -------------------------------------------------- 4 | 5 | .label { 6 | display: inline; 7 | padding: .2em .6em .3em; 8 | font-size: 75%; 9 | font-weight: bold; 10 | line-height: 1; 11 | color: @label-color; 12 | text-align: center; 13 | white-space: nowrap; 14 | vertical-align: baseline; 15 | border-radius: .25em; 16 | 17 | // Add hover effects, but only for links 18 | a& { 19 | &:hover, 20 | &:focus { 21 | color: @label-link-hover-color; 22 | text-decoration: none; 23 | cursor: pointer; 24 | } 25 | } 26 | 27 | // Empty labels collapse automatically (not available in IE8) 28 | &:empty { 29 | display: none; 30 | } 31 | 32 | // Quick fix for labels in buttons 33 | .btn & { 34 | position: relative; 35 | top: -1px; 36 | } 37 | } 38 | 39 | // Colors 40 | // Contextual variations (linked labels get darker on :hover) 41 | 42 | .label-default { 43 | .label-variant(@label-default-bg); 44 | } 45 | 46 | .label-primary { 47 | .label-variant(@label-primary-bg); 48 | } 49 | 50 | .label-success { 51 | .label-variant(@label-success-bg); 52 | } 53 | 54 | .label-info { 55 | .label-variant(@label-info-bg); 56 | } 57 | 58 | .label-warning { 59 | .label-variant(@label-warning-bg); 60 | } 61 | 62 | .label-danger { 63 | .label-variant(@label-danger-bg); 64 | } 65 | -------------------------------------------------------------------------------- /app/client/stylesheets/base/lib/bootstrap/list-group.import.less: -------------------------------------------------------------------------------- 1 | // 2 | // List groups 3 | // -------------------------------------------------- 4 | 5 | 6 | // Base class 7 | // 8 | // Easily usable on