├── .gitignore
├── .meteor
├── .finished-upgraders
├── .gitignore
├── .id
├── packages
├── platforms
├── release
└── versions
├── README.md
├── client
├── css
│ └── style.css
├── index.html
└── js
│ ├── main.js
│ └── vendor
│ └── moment.min.js
├── public
└── img
│ ├── GitHub-Mark-32px.png
│ └── browser-logos
│ ├── Readme.md
│ ├── all-desktop.png
│ ├── chrome-canary.png
│ ├── chrome.png
│ ├── chrome.svg
│ ├── chromium.png
│ ├── chromium.svg
│ ├── firefox-aurora.png
│ ├── firefox-nightly.png
│ ├── firefox.png
│ ├── firefox.svg
│ ├── ie-256.png
│ ├── ie.svg
│ ├── ie10.png
│ ├── ie10.svg
│ ├── ie6.png
│ ├── ie8-700.png
│ ├── maxthon.png
│ ├── mobile-safari.png
│ ├── opera-next.png
│ ├── opera-next.svg
│ ├── opera.png
│ ├── opera.svg
│ ├── other.png
│ ├── safari.png
│ └── webkit.png
├── server
└── server.js
└── shared.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea
--------------------------------------------------------------------------------
/.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 | notices-for-facebook-graph-api-2
9 |
--------------------------------------------------------------------------------
/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/.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 | 18owtl31c031bn11l972p
8 |
--------------------------------------------------------------------------------
/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | #
3 | # 'meteor add' and 'meteor remove' will edit this file for you,
4 | # but you can also edit it by hand.
5 |
6 | preserve-inputs
7 | d3
8 | standard-app-packages
9 |
--------------------------------------------------------------------------------
/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.1.0.3
2 |
--------------------------------------------------------------------------------
/.meteor/versions:
--------------------------------------------------------------------------------
1 | autoupdate@1.2.1
2 | base64@1.0.3
3 | binary-heap@1.0.3
4 | blaze@2.1.2
5 | blaze-tools@1.0.3
6 | boilerplate-generator@1.0.3
7 | callback-hook@1.0.3
8 | check@1.0.5
9 | d3@1.0.0
10 | ddp@1.1.0
11 | deps@1.0.7
12 | ejson@1.0.6
13 | fastclick@1.0.3
14 | geojson-utils@1.0.3
15 | html-tools@1.0.4
16 | htmljs@1.0.4
17 | http@1.1.0
18 | id-map@1.0.3
19 | jquery@1.11.3_2
20 | json@1.0.3
21 | launch-screen@1.0.2
22 | livedata@1.0.13
23 | logging@1.0.7
24 | meteor@1.1.6
25 | meteor-platform@1.2.2
26 | minifiers@1.1.5
27 | minimongo@1.0.8
28 | mobile-status-bar@1.0.3
29 | mongo@1.1.0
30 | observe-sequence@1.0.6
31 | ordered-dict@1.0.3
32 | preserve-inputs@1.0.3
33 | random@1.0.3
34 | reactive-dict@1.1.0
35 | reactive-var@1.0.5
36 | reload@1.1.3
37 | retry@1.0.3
38 | routepolicy@1.0.5
39 | session@1.1.0
40 | spacebars@1.0.6
41 | spacebars-compiler@1.0.6
42 | standard-app-packages@1.0.5
43 | templating@1.1.1
44 | tracker@1.0.7
45 | ui@1.0.6
46 | underscore@1.0.3
47 | url@1.0.4
48 | webapp@1.2.0
49 | webapp-hashing@1.0.3
50 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Browpie
2 | =======
3 |
4 | Pie charts showing browser usage over the last hour, day, month and year. Built using [MeteorJS](http://www.meteor.com/), the pie charts automatically update themselves as stats are collected.
5 |
6 | [http://browpie.meteor.com](http://browpie.meteor.com/)
7 |
--------------------------------------------------------------------------------
/client/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #eee;
3 | margin: 0;
4 | padding: 1em;
5 | }
6 | h1, h2 {
7 | margin: 0;
8 | }
9 | h1 {
10 | font: 300 60px "Helvetica Neue",Helvetica,Arial,sans-serif;
11 | color: #353535;
12 | }
13 | h2 {
14 | font: 100 30px/0.75 "Helvetica Neue",Helvetica,Arial,sans-serif;
15 | color: #cecece;
16 | }
17 | hgroup {
18 | margin-bottom: 2em;
19 | }
20 | .pie {
21 | width: 320px;
22 | margin: 0 auto;
23 | }
24 | .pie h2 {
25 | font-size: 16px;
26 | font-weight: 300;
27 | color: #353535;
28 | }
29 | #gh {
30 | position: absolute;
31 | top: 2em;
32 | right: 1em;
33 | opacity: 0.15;
34 | transition: opacity 0.25s linear;
35 | }
36 | #gh:hover {
37 | opacity: 1;
38 | }
39 | @media only screen and (min-width: 768px) {
40 | body {
41 | padding: 1em 3em;
42 | }
43 | .pie {
44 | width: 500px;
45 | }
46 | .pie h2 {
47 | position: relative;
48 | top: 255px;
49 | left: -6em;
50 | }
51 | #gh {
52 | right: 3em;
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/client/index.html:
--------------------------------------------------------------------------------
1 |
2 | meteor-browpie
3 |
4 |
5 |
6 |
7 | Browpie
8 | Realtime browser stat pies
9 |
10 |
11 |
Last Hour
12 |
13 |
14 |
Last Day
15 |
16 |
17 |
Last Month
18 |
19 |
20 |
Last Year
21 |
22 |
23 |
--------------------------------------------------------------------------------
/client/js/main.js:
--------------------------------------------------------------------------------
1 | // The time periods that our pie charts will show
2 | var periods = ['hour', 'day', 'month', 'year'];
3 |
4 | function getBoundaries() {
5 | return periods.map(function(period) {
6 | return moment().subtract(1, period);
7 | });
8 | }
9 |
10 | // Agent groupings
11 | var AgentGroup = {
12 | IEMobile: 'IE Mobile',
13 | IE: 'IE',
14 | OperaMini: 'Opera Mini',
15 | Opera: 'Opera',
16 | Chrome: 'Chrome',
17 | MobileSafari: 'Mobile Safari',
18 | Safari: 'Safari',
19 | Firefox: 'Firefox',
20 | Other: 'Other'
21 | };
22 |
23 | Meteor.startup(function() {
24 |
25 | UserAgents.insert({str: navigator.userAgent, created: moment().toDate()});
26 |
27 | var boundaries = getBoundaries();
28 |
29 | Meteor.subscribe('agents', boundaries[boundaries.length - 1].toDate());
30 |
31 | // Do some d3 when the UserAgents collection changes.
32 | Tracker.autorun(debounceRenderPies);
33 |
34 | // Do some d3 when some time has elapsed
35 | Meteor.setInterval(debounceRenderPies, 30000);
36 | });
37 |
38 | var debounceRenderPies = (function() {
39 | var scheduled = false;
40 | return function() {
41 | console.log('User agents count', UserAgents.find({}).fetch().length);
42 | if (!scheduled) {
43 | scheduled = true;
44 | Meteor.setTimeout(function() {
45 | scheduled = false;
46 | renderPies();
47 | }, 500);
48 | }
49 | };
50 | })();
51 |
52 | function renderPies() {
53 |
54 | console.log("renderPies @ " + (new Date));
55 |
56 | getBoundaries().forEach(function(boundary, i) {
57 |
58 | var agents = UserAgents.findByCreatedGreaterThan(boundary.toDate());
59 |
60 | if(!agents.count()) {
61 | return;
62 | }
63 |
64 | var data = pieData(agents);
65 |
66 | var pieDim = Math.min(document.getElementById(periods[i]).clientWidth, 500),
67 | radius = pieDim / 2;
68 |
69 | var arc = d3.svg.arc()
70 | .outerRadius(radius - 10)
71 | .innerRadius(0);
72 |
73 | var pie = d3.layout.pie()
74 | .sort(null)
75 | .value(function(d) { return d.count; });
76 |
77 | var svg = d3.select('#'+ periods[i] + ' svg > g');
78 |
79 | if(svg.empty()) {
80 | svg = d3.select('#' + periods[i]).append("svg")
81 | .attr("width", pieDim)
82 | .attr("height", pieDim)
83 | .append("g")
84 | .attr("transform", "translate(" + radius + "," + radius + ")");
85 | }
86 |
87 | var slice = svg.selectAll(".arc").data(pie(data), function(d) { return d.data.name; });
88 |
89 | var sliceEnter = slice.enter()
90 | .append("g")
91 | .attr("class", "arc");
92 |
93 | sliceEnter.append("path")
94 | .style("fill", function(d) { return d.data.colour; })
95 | .style('stroke', '#fff')
96 | .style('stroke-width', 0.02 * pieDim)
97 | .style('stroke-linejoin', 'bevel');
98 |
99 | var imageDim = 0.14 * pieDim;
100 |
101 | sliceEnter.append('image')
102 | .attr('xlink:href', function(d) { return d.data.image; })
103 | .attr('preserveAspectRatio', 'none')
104 | .attr('width', imageDim)
105 | .attr('height', imageDim);
106 |
107 | var sliceUpdate = slice.transition();
108 |
109 | sliceUpdate.select('path')
110 | .attr("d", arc);
111 |
112 | sliceUpdate.select("image")
113 | .attr("transform", function(d) {
114 | var centroid = arc.centroid(d);
115 | return "translate(" + (centroid[0] - (imageDim / 2)) + ',' + (centroid[1] - (imageDim / 2)) + ")";
116 | });
117 |
118 | slice.exit().remove();
119 | });
120 | }
121 |
122 | // Convert a bunch of agents into data for a pie chart
123 | function pieData(agents) {
124 | var agentMap = {};
125 |
126 | // Count the grouped agents
127 | agents.forEach(function(agent) {
128 | var group = groupAgent(agent.str);
129 | agentMap[group] = agentMap[group] ? agentMap[group] + 1 : 1;
130 | });
131 |
132 | // Convert to array
133 | return Object.keys(agentMap).map(function(groupName) {
134 | return {
135 | name: groupName,
136 | count: agentMap[groupName],
137 | colour: groupColour(groupName),
138 | image: '/img/browser-logos/' + groupImage(groupName) + '.png'
139 | };
140 | });
141 | }
142 |
143 | // Converts a user agent string into an agent group
144 | function groupAgent(agent) {
145 |
146 | if(agent.indexOf('Chrome') != -1) {
147 | return AgentGroup.Chrome;
148 | } else if(agent.indexOf('Firefox') != -1) {
149 | return AgentGroup.Firefox;
150 | } else if(agent.indexOf('Opera') != -1) {
151 | return AgentGroup.Opera;
152 | } else if(agent.indexOf('Safari') != -1 && agent.indexOf('Mobile') != -1) {
153 | return AgentGroup.MobileSafari;
154 | } else if(agent.indexOf('Safari') != -1) {
155 | return AgentGroup.Safari;
156 | // Group the UIWebView browsers in apps as Mobile Safari
157 | } else if(agent.indexOf('iPhone') != -1 || agent.indexOf('iPad') != -1) {
158 | return AgentGroup.MobileSafari;
159 | } else if(agent.indexOf('IE Mobile') != -1) {
160 | return AgentGroup.IEMobile;
161 | } else if(agent.indexOf('IE') != -1 || agent.indexOf('Trident') != -1) {
162 | return AgentGroup.IE;
163 | }
164 | return AgentGroup.Other;
165 | }
166 |
167 | // Converts a group name into a colour
168 | function groupColour(group) {
169 | switch(group) {
170 | case AgentGroup.IEMobile: return '#194371';
171 | case AgentGroup.IE: return '#194371';
172 | case AgentGroup.Opera: return '#CC0F16';
173 | case AgentGroup.Chrome: return '#4db849';
174 | case AgentGroup.MobileSafari: return '#3b98d5';
175 | case AgentGroup.Safari: return '#3b98d5';
176 | case AgentGroup.Firefox: return '#dd7210';
177 | default: return '#000';
178 | }
179 | }
180 |
181 | // Converts a group name into an image name
182 | function groupImage(group) {
183 | switch(group) {
184 | case AgentGroup.IEMobile: return 'ie10';
185 | case AgentGroup.IE: return 'ie8-700';
186 | case AgentGroup.Opera: return 'opera';
187 | case AgentGroup.Chrome: return 'chrome';
188 | case AgentGroup.MobileSafari: return 'mobile-safari';
189 | case AgentGroup.Safari: return 'safari';
190 | case AgentGroup.Firefox: return 'firefox';
191 | default: return 'other';
192 | }
193 | }
194 |
195 |
--------------------------------------------------------------------------------
/client/js/vendor/moment.min.js:
--------------------------------------------------------------------------------
1 | // moment.js
2 | // version : 2.0.0
3 | // author : Tim Wood
4 | // license : MIT
5 | // momentjs.com
6 | (function(e){function O(e,t){return function(n){return j(e.call(this,n),t)}}function M(e){return function(t){return this.lang().ordinal(e.call(this,t))}}function _(){}function D(e){H(this,e)}function P(e){var t=this._data={},n=e.years||e.year||e.y||0,r=e.months||e.month||e.M||0,i=e.weeks||e.week||e.w||0,s=e.days||e.day||e.d||0,o=e.hours||e.hour||e.h||0,u=e.minutes||e.minute||e.m||0,a=e.seconds||e.second||e.s||0,f=e.milliseconds||e.millisecond||e.ms||0;this._milliseconds=f+a*1e3+u*6e4+o*36e5,this._days=s+i*7,this._months=r+n*12,t.milliseconds=f%1e3,a+=B(f/1e3),t.seconds=a%60,u+=B(a/60),t.minutes=u%60,o+=B(u/60),t.hours=o%24,s+=B(o/24),s+=i*7,t.days=s%30,r+=B(s/30),t.months=r%12,n+=B(r/12),t.years=n}function H(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function B(e){return e<0?Math.ceil(e):Math.floor(e)}function j(e,t){var n=e+"";while(n.length68?1900:2e3);break;case"YYYY":case"YYYYY":s[0]=~~t;break;case"a":case"A":n._isPm=(t+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":s[3]=~~t;break;case"m":case"mm":s[4]=~~t;break;case"s":case"ss":s[5]=~~t;break;case"S":case"SS":case"SSS":s[6]=~~(("0."+t)*1e3);break;case"X":n._d=new Date(parseFloat(t)*1e3);break;case"Z":case"ZZ":n._useUTC=!0,r=(t+"").match(x),r&&r[1]&&(n._tzh=~~r[1]),r&&r[2]&&(n._tzm=~~r[2]),r&&r[0]==="+"&&(n._tzh=-n._tzh,n._tzm=-n._tzm)}t==null&&(n._isValid=!1)}function J(e){var t,n,r=[];if(e._d)return;for(t=0;t<7;t++)e._a[t]=r[t]=e._a[t]==null?t===2?1:0:e._a[t];r[3]+=e._tzh||0,r[4]+=e._tzm||0,n=new Date(0),e._useUTC?(n.setUTCFullYear(r[0],r[1],r[2]),n.setUTCHours(r[3],r[4],r[5],r[6])):(n.setFullYear(r[0],r[1],r[2]),n.setHours(r[3],r[4],r[5],r[6])),e._d=n}function K(e){var t=e._f.match(a),n=e._i,r,i;e._a=[];for(r=0;r0,f[4]=n,Z.apply({},f)}function tt(e,n,r){var i=r-n,s=r-e.day();return s>i&&(s-=7),s11?n?"pm":"PM":n?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},calendar:function(e,t){var n=this._calendar[e];return typeof n=="function"?n.apply(t):n},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(e,t,n,r){var i=this._relativeTime[n];return typeof i=="function"?i(e,t,n,r):i.replace(/%d/i,e)},pastFuture:function(e,t){var n=this._relativeTime[e>0?"future":"past"];return typeof n=="function"?n(t):n.replace(/%s/i,t)},ordinal:function(e){return this._ordinal.replace("%d",e)},_ordinal:"%d",preparse:function(e){return e},postformat:function(e){return e},week:function(e){return tt(e,this._week.dow,this._week.doy)},_week:{dow:0,doy:6}},t=function(e,t,n){return nt({_i:e,_f:t,_l:n,_isUTC:!1})},t.utc=function(e,t,n){return nt({_useUTC:!0,_isUTC:!0,_l:n,_i:e,_f:t})},t.unix=function(e){return t(e*1e3)},t.duration=function(e,n){var r=t.isDuration(e),i=typeof e=="number",s=r?e._data:i?{}:e,o;return i&&(n?s[n]=e:s.milliseconds=e),o=new P(s),r&&e.hasOwnProperty("_lang")&&(o._lang=e._lang),o},t.version=n,t.defaultFormat=E,t.lang=function(e,n){var r;if(!e)return t.fn._lang._abbr;n?R(e,n):s[e]||U(e),t.duration.fn._lang=t.fn._lang=U(e)},t.langData=function(e){return e&&e._lang&&e._lang._abbr&&(e=e._lang._abbr),U(e)},t.isMoment=function(e){return e instanceof D},t.isDuration=function(e){return e instanceof P},t.fn=D.prototype={clone:function(){return t(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._d},toJSON:function(){return t.utc(this).format("YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var e=this;return[e.year(),e.month(),e.date(),e.hours(),e.minutes(),e.seconds(),e.milliseconds()]},isValid:function(){return this._isValid==null&&(this._a?this._isValid=!q(this._a,(this._isUTC?t.utc(this._a):t(this._a)).toArray()):this._isValid=!isNaN(this._d.getTime())),!!this._isValid},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(e){var n=X(this,e||t.defaultFormat);return this.lang().postformat(n)},add:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,1),this},subtract:function(e,n){var r;return typeof e=="string"?r=t.duration(+n,e):r=t.duration(e,n),F(this,r,-1),this},diff:function(e,n,r){var i=this._isUTC?t(e).utc():t(e).local(),s=(this.zone()-i.zone())*6e4,o,u;return n&&(n=n.replace(/s$/,"")),n==="year"||n==="month"?(o=(this.daysInMonth()+i.daysInMonth())*432e5,u=(this.year()-i.year())*12+(this.month()-i.month()),u+=(this-t(this).startOf("month")-(i-t(i).startOf("month")))/o,n==="year"&&(u/=12)):(o=this-i-s,u=n==="second"?o/1e3:n==="minute"?o/6e4:n==="hour"?o/36e5:n==="day"?o/864e5:n==="week"?o/6048e5:o),r?u:B(u)},from:function(e,n){return t.duration(this.diff(e)).lang(this.lang()._abbr).humanize(!n)},fromNow:function(e){return this.from(t(),e)},calendar:function(){var e=this.diff(t().startOf("day"),"days",!0),n=e<-6?"sameElse":e<-1?"lastWeek":e<0?"lastDay":e<1?"sameDay":e<2?"nextDay":e<7?"nextWeek":"sameElse";return this.format(this.lang().calendar(n,this))},isLeapYear:function(){var e=this.year();return e%4===0&&e%100!==0||e%400===0},isDST:function(){return this.zone()+t(e).startOf(n)},isBefore:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)<+t(e).startOf(n)},isSame:function(e,n){return n=typeof n!="undefined"?n:"millisecond",+this.clone().startOf(n)===+t(e).startOf(n)},zone:function(){return this._isUTC?0:this._d.getTimezoneOffset()},daysInMonth:function(){return t.utc([this.year(),this.month()+1,0]).date()},dayOfYear:function(e){var n=r((t(this).startOf("day")-t(this).startOf("year"))/864e5)+1;return e==null?n:this.add("d",e-n)},isoWeek:function(e){var t=tt(this,1,4);return e==null?t:this.add("d",(e-t)*7)},week:function(e){var t=this.lang().week(this);return e==null?t:this.add("d",(e-t)*7)},lang:function(t){return t===e?this._lang:(this._lang=U(t),this)}};for(i=0;i
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/img/browser-logos/chromium.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/chromium.png
--------------------------------------------------------------------------------
/public/img/browser-logos/chromium.svg:
--------------------------------------------------------------------------------
1 |
54 |
--------------------------------------------------------------------------------
/public/img/browser-logos/firefox-aurora.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/firefox-aurora.png
--------------------------------------------------------------------------------
/public/img/browser-logos/firefox-nightly.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/firefox-nightly.png
--------------------------------------------------------------------------------
/public/img/browser-logos/firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/firefox.png
--------------------------------------------------------------------------------
/public/img/browser-logos/firefox.svg:
--------------------------------------------------------------------------------
1 |
415 |
--------------------------------------------------------------------------------
/public/img/browser-logos/ie-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/ie-256.png
--------------------------------------------------------------------------------
/public/img/browser-logos/ie.svg:
--------------------------------------------------------------------------------
1 |
41 |
--------------------------------------------------------------------------------
/public/img/browser-logos/ie10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/ie10.png
--------------------------------------------------------------------------------
/public/img/browser-logos/ie10.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/public/img/browser-logos/ie6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/ie6.png
--------------------------------------------------------------------------------
/public/img/browser-logos/ie8-700.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/ie8-700.png
--------------------------------------------------------------------------------
/public/img/browser-logos/maxthon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/maxthon.png
--------------------------------------------------------------------------------
/public/img/browser-logos/mobile-safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/mobile-safari.png
--------------------------------------------------------------------------------
/public/img/browser-logos/opera-next.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/opera-next.png
--------------------------------------------------------------------------------
/public/img/browser-logos/opera-next.svg:
--------------------------------------------------------------------------------
1 |
248 |
--------------------------------------------------------------------------------
/public/img/browser-logos/opera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/opera.png
--------------------------------------------------------------------------------
/public/img/browser-logos/opera.svg:
--------------------------------------------------------------------------------
1 |
112 |
--------------------------------------------------------------------------------
/public/img/browser-logos/other.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/other.png
--------------------------------------------------------------------------------
/public/img/browser-logos/safari.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/safari.png
--------------------------------------------------------------------------------
/public/img/browser-logos/webkit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/alanshaw/meteor-browpie/3b2d2a6c8d5df1c436db46d077173c15b251f02a/public/img/browser-logos/webkit.png
--------------------------------------------------------------------------------
/server/server.js:
--------------------------------------------------------------------------------
1 | Meteor.publish('agents', function(after) {
2 | return UserAgents.findByCreatedGreaterThan(after);
3 | });
--------------------------------------------------------------------------------
/shared.js:
--------------------------------------------------------------------------------
1 | UserAgents = new Mongo.Collection('agents');
2 |
3 | UserAgents.allow({
4 | insert: function() {
5 | return true;
6 | }
7 | });
8 |
9 | UserAgents.findByCreatedGreaterThan = function(after) {
10 | return UserAgents.find({created: {$gt: after}}, {sort: [['created', 'desc']]});
11 | };
--------------------------------------------------------------------------------