├── .babelrc
├── .gitignore
├── README.md
├── assets
├── css
│ ├── plugins
│ │ └── fancybox
│ │ │ ├── blank.gif
│ │ │ ├── fancybox_loading.gif
│ │ │ ├── fancybox_overlay.png
│ │ │ ├── fancybox_sprite.png
│ │ │ ├── helpers
│ │ │ ├── fancybox_buttons.png
│ │ │ ├── jquery.fancybox-buttons.css
│ │ │ ├── jquery.fancybox-buttons.js
│ │ │ ├── jquery.fancybox-media.js
│ │ │ ├── jquery.fancybox-thumbs.css
│ │ │ └── jquery.fancybox-thumbs.js
│ │ │ └── jquery.fancybox.css
│ ├── style.css
│ └── style.min.css
├── fonts
│ ├── fonts
│ │ ├── Grands.eot
│ │ ├── Grands.svg
│ │ ├── Grands.ttf
│ │ └── Grands.woff
│ └── grand.css
└── img
│ ├── page
│ ├── auth.png
│ ├── auth_h.png
│ └── blur.jpg
│ └── user
│ ├── heart.png
│ └── video-play.png
├── auth.html
├── bundle.js
├── gulpfile.js
├── icon-app.png
├── package.json
├── react
└── index.html
├── src
├── app
│ ├── Root.jsx
│ ├── actions
│ │ ├── followers.js
│ │ ├── index.js
│ │ ├── profile.js
│ │ ├── searchByTag.js
│ │ ├── searchByUser.js
│ │ └── timeline.js
│ ├── api
│ │ └── index.js
│ ├── constants
│ │ └── index.js
│ ├── handlers
│ │ ├── App.jsx
│ │ ├── Followers.jsx
│ │ ├── PageNotFound.jsx
│ │ ├── Profile.jsx
│ │ ├── SearchPhotos.jsx
│ │ ├── SearchUsers.jsx
│ │ └── Timeline.jsx
│ ├── reducers
│ │ ├── followers.js
│ │ ├── index.js
│ │ ├── profile.js
│ │ ├── searchByTag.js
│ │ ├── searchByUser.js
│ │ └── timeline.js
│ └── store
│ │ └── index.js
├── helpers
│ └── index.js
└── stylus
│ ├── _about.styl
│ ├── _column.styl
│ ├── _comments.styl
│ ├── _feed.styl
│ ├── _follow.styl
│ ├── _fonts.styl
│ ├── _footer.styl
│ ├── _form.styl
│ ├── _globals.styl
│ ├── _grid.styl
│ ├── _header.styl
│ ├── _loader.styl
│ ├── _main.styl
│ ├── _menu.styl
│ ├── _mixins.styl
│ ├── _normalize.styl
│ ├── _page.styl
│ ├── _photo-list.styl
│ ├── _photo.styl
│ ├── _popup.styl
│ ├── _profile.styl
│ ├── _responsive.styl
│ ├── _row.styl
│ ├── _search.styl
│ ├── _sidebar.styl
│ ├── _social.styl
│ ├── _user.styl
│ ├── _vars.styl
│ └── style.styl
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015", "stage-0", "react"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .gitignore
3 | .module-cache
4 | node_modules
5 | index.html
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | React Instagram App
2 | ==
3 |
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/blank.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/css/plugins/fancybox/blank.gif
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/fancybox_loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/css/plugins/fancybox/fancybox_loading.gif
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/fancybox_overlay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/css/plugins/fancybox/fancybox_overlay.png
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/fancybox_sprite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/css/plugins/fancybox/fancybox_sprite.png
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/helpers/fancybox_buttons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/css/plugins/fancybox/helpers/fancybox_buttons.png
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/helpers/jquery.fancybox-buttons.css:
--------------------------------------------------------------------------------
1 | #fancybox-buttons {
2 | position: fixed;
3 | left: 0;
4 | width: 100%;
5 | z-index: 8050;
6 | }
7 |
8 | #fancybox-buttons.top {
9 | top: 10px;
10 | }
11 |
12 | #fancybox-buttons.bottom {
13 | bottom: 10px;
14 | }
15 |
16 | #fancybox-buttons ul {
17 | display: block;
18 | width: 166px;
19 | height: 30px;
20 | margin: 0 auto;
21 | padding: 0;
22 | list-style: none;
23 | border: 1px solid #111;
24 | border-radius: 3px;
25 | -webkit-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
26 | -moz-box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
27 | box-shadow: inset 0 0 0 1px rgba(255,255,255,.05);
28 | background: rgb(50,50,50);
29 | background: -moz-linear-gradient(top, rgb(68,68,68) 0%, rgb(52,52,52) 50%, rgb(41,41,41) 50%, rgb(51,51,51) 100%);
30 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgb(68,68,68)), color-stop(50%,rgb(52,52,52)), color-stop(50%,rgb(41,41,41)), color-stop(100%,rgb(51,51,51)));
31 | background: -webkit-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
32 | background: -o-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
33 | background: -ms-linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
34 | background: linear-gradient(top, rgb(68,68,68) 0%,rgb(52,52,52) 50%,rgb(41,41,41) 50%,rgb(51,51,51) 100%);
35 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#444444', endColorstr='#222222',GradientType=0 );
36 | }
37 |
38 | #fancybox-buttons ul li {
39 | float: left;
40 | margin: 0;
41 | padding: 0;
42 | }
43 |
44 | #fancybox-buttons a {
45 | display: block;
46 | width: 30px;
47 | height: 30px;
48 | text-indent: -9999px;
49 | background-image: url('fancybox_buttons.png');
50 | background-repeat: no-repeat;
51 | outline: none;
52 | opacity: 0.8;
53 | }
54 |
55 | #fancybox-buttons a:hover {
56 | opacity: 1;
57 | }
58 |
59 | #fancybox-buttons a.btnPrev {
60 | background-position: 5px 0;
61 | }
62 |
63 | #fancybox-buttons a.btnNext {
64 | background-position: -33px 0;
65 | border-right: 1px solid #3e3e3e;
66 | }
67 |
68 | #fancybox-buttons a.btnPlay {
69 | background-position: 0 -30px;
70 | }
71 |
72 | #fancybox-buttons a.btnPlayOn {
73 | background-position: -30px -30px;
74 | }
75 |
76 | #fancybox-buttons a.btnToggle {
77 | background-position: 3px -60px;
78 | border-left: 1px solid #111;
79 | border-right: 1px solid #3e3e3e;
80 | width: 35px
81 | }
82 |
83 | #fancybox-buttons a.btnToggleOn {
84 | background-position: -27px -60px;
85 | }
86 |
87 | #fancybox-buttons a.btnClose {
88 | border-left: 1px solid #111;
89 | width: 35px;
90 | background-position: -56px 0px;
91 | }
92 |
93 | #fancybox-buttons a.btnDisabled {
94 | opacity : 0.4;
95 | cursor: default;
96 | }
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/helpers/jquery.fancybox-buttons.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Buttons helper for fancyBox
3 | * version: 1.0.5 (Mon, 15 Oct 2012)
4 | * @requires fancyBox v2.0 or later
5 | *
6 | * Usage:
7 | * $(".fancybox").fancybox({
8 | * helpers : {
9 | * buttons: {
10 | * position : 'top'
11 | * }
12 | * }
13 | * });
14 | *
15 | */
16 | (function ($) {
17 | //Shortcut for fancyBox object
18 | var F = $.fancybox;
19 |
20 | //Add helper object
21 | F.helpers.buttons = {
22 | defaults : {
23 | skipSingle : false, // disables if gallery contains single image
24 | position : 'top', // 'top' or 'bottom'
25 | tpl : '
'
26 | },
27 |
28 | list : null,
29 | buttons: null,
30 |
31 | beforeLoad: function (opts, obj) {
32 | //Remove self if gallery do not have at least two items
33 |
34 | if (opts.skipSingle && obj.group.length < 2) {
35 | obj.helpers.buttons = false;
36 | obj.closeBtn = true;
37 |
38 | return;
39 | }
40 |
41 | //Increase top margin to give space for buttons
42 | obj.margin[ opts.position === 'bottom' ? 2 : 0 ] += 30;
43 | },
44 |
45 | onPlayStart: function () {
46 | if (this.buttons) {
47 | this.buttons.play.attr('title', 'Pause slideshow').addClass('btnPlayOn');
48 | }
49 | },
50 |
51 | onPlayEnd: function () {
52 | if (this.buttons) {
53 | this.buttons.play.attr('title', 'Start slideshow').removeClass('btnPlayOn');
54 | }
55 | },
56 |
57 | afterShow: function (opts, obj) {
58 | var buttons = this.buttons;
59 |
60 | if (!buttons) {
61 | this.list = $(opts.tpl).addClass(opts.position).appendTo('body');
62 |
63 | buttons = {
64 | prev : this.list.find('.btnPrev').click( F.prev ),
65 | next : this.list.find('.btnNext').click( F.next ),
66 | play : this.list.find('.btnPlay').click( F.play ),
67 | toggle : this.list.find('.btnToggle').click( F.toggle )
68 | }
69 | }
70 |
71 | //Prev
72 | if (obj.index > 0 || obj.loop) {
73 | buttons.prev.removeClass('btnDisabled');
74 | } else {
75 | buttons.prev.addClass('btnDisabled');
76 | }
77 |
78 | //Next / Play
79 | if (obj.loop || obj.index < obj.group.length - 1) {
80 | buttons.next.removeClass('btnDisabled');
81 | buttons.play.removeClass('btnDisabled');
82 |
83 | } else {
84 | buttons.next.addClass('btnDisabled');
85 | buttons.play.addClass('btnDisabled');
86 | }
87 |
88 | this.buttons = buttons;
89 |
90 | this.onUpdate(opts, obj);
91 | },
92 |
93 | onUpdate: function (opts, obj) {
94 | var toggle;
95 |
96 | if (!this.buttons) {
97 | return;
98 | }
99 |
100 | toggle = this.buttons.toggle.removeClass('btnDisabled btnToggleOn');
101 |
102 | //Size toggle button
103 | if (obj.canShrink) {
104 | toggle.addClass('btnToggleOn');
105 |
106 | } else if (!obj.canExpand) {
107 | toggle.addClass('btnDisabled');
108 | }
109 | },
110 |
111 | beforeClose: function () {
112 | if (this.list) {
113 | this.list.remove();
114 | }
115 |
116 | this.list = null;
117 | this.buttons = null;
118 | }
119 | };
120 |
121 | }(jQuery));
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/helpers/jquery.fancybox-media.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Media helper for fancyBox
3 | * version: 1.0.5 (Tue, 23 Oct 2012)
4 | * @requires fancyBox v2.0 or later
5 | *
6 | * Usage:
7 | * $(".fancybox").fancybox({
8 | * helpers : {
9 | * media: true
10 | * }
11 | * });
12 | *
13 | * Set custom URL parameters:
14 | * $(".fancybox").fancybox({
15 | * helpers : {
16 | * media: {
17 | * youtube : {
18 | * params : {
19 | * autoplay : 0
20 | * }
21 | * }
22 | * }
23 | * }
24 | * });
25 | *
26 | * Or:
27 | * $(".fancybox").fancybox({,
28 | * helpers : {
29 | * media: true
30 | * },
31 | * youtube : {
32 | * autoplay: 0
33 | * }
34 | * });
35 | *
36 | * Supports:
37 | *
38 | * Youtube
39 | * http://www.youtube.com/watch?v=opj24KnzrWo
40 | * http://www.youtube.com/embed/opj24KnzrWo
41 | * http://youtu.be/opj24KnzrWo
42 | * Vimeo
43 | * http://vimeo.com/40648169
44 | * http://vimeo.com/channels/staffpicks/38843628
45 | * http://vimeo.com/groups/surrealism/videos/36516384
46 | * http://player.vimeo.com/video/45074303
47 | * Metacafe
48 | * http://www.metacafe.com/watch/7635964/dr_seuss_the_lorax_movie_trailer/
49 | * http://www.metacafe.com/watch/7635964/
50 | * Dailymotion
51 | * http://www.dailymotion.com/video/xoytqh_dr-seuss-the-lorax-premiere_people
52 | * Twitvid
53 | * http://twitvid.com/QY7MD
54 | * Twitpic
55 | * http://twitpic.com/7p93st
56 | * Instagram
57 | * http://instagr.am/p/IejkuUGxQn/
58 | * http://instagram.com/p/IejkuUGxQn/
59 | * Google maps
60 | * http://maps.google.com/maps?q=Eiffel+Tower,+Avenue+Gustave+Eiffel,+Paris,+France&t=h&z=17
61 | * http://maps.google.com/?ll=48.857995,2.294297&spn=0.007666,0.021136&t=m&z=16
62 | * http://maps.google.com/?ll=48.859463,2.292626&spn=0.000965,0.002642&t=m&z=19&layer=c&cbll=48.859524,2.292532&panoid=YJ0lq28OOy3VT2IqIuVY0g&cbp=12,151.58,,0,-15.56
63 | */
64 | (function ($) {
65 | "use strict";
66 |
67 | //Shortcut for fancyBox object
68 | var F = $.fancybox,
69 | format = function( url, rez, params ) {
70 | params = params || '';
71 |
72 | if ( $.type( params ) === "object" ) {
73 | params = $.param(params, true);
74 | }
75 |
76 | $.each(rez, function(key, value) {
77 | url = url.replace( '$' + key, value || '' );
78 | });
79 |
80 | if (params.length) {
81 | url += ( url.indexOf('?') > 0 ? '&' : '?' ) + params;
82 | }
83 |
84 | return url;
85 | };
86 |
87 | //Add helper object
88 | F.helpers.media = {
89 | defaults : {
90 | youtube : {
91 | matcher : /(youtube\.com|youtu\.be)\/(watch\?v=|v\/|u\/|embed\/?)?(videoseries\?list=(.*)|[\w-]{11}|\?listType=(.*)&list=(.*)).*/i,
92 | params : {
93 | autoplay : 1,
94 | autohide : 1,
95 | fs : 1,
96 | rel : 0,
97 | hd : 1,
98 | wmode : 'opaque',
99 | enablejsapi : 1
100 | },
101 | type : 'iframe',
102 | url : '//www.youtube.com/embed/$3'
103 | },
104 | vimeo : {
105 | matcher : /(?:vimeo(?:pro)?.com)\/(?:[^\d]+)?(\d+)(?:.*)/,
106 | params : {
107 | autoplay : 1,
108 | hd : 1,
109 | show_title : 1,
110 | show_byline : 1,
111 | show_portrait : 0,
112 | fullscreen : 1
113 | },
114 | type : 'iframe',
115 | url : '//player.vimeo.com/video/$1'
116 | },
117 | metacafe : {
118 | matcher : /metacafe.com\/(?:watch|fplayer)\/([\w\-]{1,10})/,
119 | params : {
120 | autoPlay : 'yes'
121 | },
122 | type : 'swf',
123 | url : function( rez, params, obj ) {
124 | obj.swf.flashVars = 'playerVars=' + $.param( params, true );
125 |
126 | return '//www.metacafe.com/fplayer/' + rez[1] + '/.swf';
127 | }
128 | },
129 | dailymotion : {
130 | matcher : /dailymotion.com\/video\/(.*)\/?(.*)/,
131 | params : {
132 | additionalInfos : 0,
133 | autoStart : 1
134 | },
135 | type : 'swf',
136 | url : '//www.dailymotion.com/swf/video/$1'
137 | },
138 | twitvid : {
139 | matcher : /twitvid\.com\/([a-zA-Z0-9_\-\?\=]+)/i,
140 | params : {
141 | autoplay : 0
142 | },
143 | type : 'iframe',
144 | url : '//www.twitvid.com/embed.php?guid=$1'
145 | },
146 | twitpic : {
147 | matcher : /twitpic\.com\/(?!(?:place|photos|events)\/)([a-zA-Z0-9\?\=\-]+)/i,
148 | type : 'image',
149 | url : '//twitpic.com/show/full/$1/'
150 | },
151 | instagram : {
152 | matcher : /(instagr\.am|instagram\.com)\/p\/([a-zA-Z0-9_\-]+)\/?/i,
153 | type : 'image',
154 | url : '//$1/p/$2/media/'
155 | },
156 | google_maps : {
157 | matcher : /maps\.google\.([a-z]{2,3}(\.[a-z]{2})?)\/(\?ll=|maps\?)(.*)/i,
158 | type : 'iframe',
159 | url : function( rez ) {
160 | return '//maps.google.' + rez[1] + '/' + rez[3] + '' + rez[4] + '&output=' + (rez[4].indexOf('layer=c') > 0 ? 'svembed' : 'embed');
161 | }
162 | }
163 | },
164 |
165 | beforeLoad : function(opts, obj) {
166 | var url = obj.href || '',
167 | type = false,
168 | what,
169 | item,
170 | rez,
171 | params;
172 |
173 | for (what in opts) {
174 | item = opts[ what ];
175 | rez = url.match( item.matcher );
176 |
177 | if (rez) {
178 | type = item.type;
179 | params = $.extend(true, {}, item.params, obj[ what ] || ($.isPlainObject(opts[ what ]) ? opts[ what ].params : null));
180 |
181 | url = $.type( item.url ) === "function" ? item.url.call( this, rez, params, obj ) : format( item.url, rez, params );
182 |
183 | break;
184 | }
185 | }
186 |
187 | if (type) {
188 | obj.href = url;
189 | obj.type = type;
190 |
191 | obj.autoHeight = false;
192 | }
193 | }
194 | };
195 |
196 | }(jQuery));
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/helpers/jquery.fancybox-thumbs.css:
--------------------------------------------------------------------------------
1 | #fancybox-thumbs {
2 | position: fixed;
3 | left: 0;
4 | width: 100%;
5 | overflow: hidden;
6 | z-index: 8050;
7 | }
8 |
9 | #fancybox-thumbs.bottom {
10 | bottom: 2px;
11 | }
12 |
13 | #fancybox-thumbs.top {
14 | top: 2px;
15 | }
16 |
17 | #fancybox-thumbs ul {
18 | position: relative;
19 | list-style: none;
20 | margin: 0;
21 | padding: 0;
22 | }
23 |
24 | #fancybox-thumbs ul li {
25 | float: left;
26 | padding: 1px;
27 | opacity: 0.5;
28 | }
29 |
30 | #fancybox-thumbs ul li.active {
31 | opacity: 0.75;
32 | padding: 0;
33 | border: 1px solid #fff;
34 | }
35 |
36 | #fancybox-thumbs ul li:hover {
37 | opacity: 1;
38 | }
39 |
40 | #fancybox-thumbs ul li a {
41 | display: block;
42 | position: relative;
43 | overflow: hidden;
44 | border: 1px solid #222;
45 | background: #111;
46 | outline: none;
47 | }
48 |
49 | #fancybox-thumbs ul li img {
50 | display: block;
51 | position: relative;
52 | border: 0;
53 | padding: 0;
54 | }
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/helpers/jquery.fancybox-thumbs.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Thumbnail helper for fancyBox
3 | * version: 1.0.7 (Mon, 01 Oct 2012)
4 | * @requires fancyBox v2.0 or later
5 | *
6 | * Usage:
7 | * $(".fancybox").fancybox({
8 | * helpers : {
9 | * thumbs: {
10 | * width : 50,
11 | * height : 50
12 | * }
13 | * }
14 | * });
15 | *
16 | */
17 | (function ($) {
18 | //Shortcut for fancyBox object
19 | var F = $.fancybox;
20 |
21 | //Add helper object
22 | F.helpers.thumbs = {
23 | defaults : {
24 | width : 50, // thumbnail width
25 | height : 50, // thumbnail height
26 | position : 'bottom', // 'top' or 'bottom'
27 | source : function ( item ) { // function to obtain the URL of the thumbnail image
28 | var href;
29 |
30 | if (item.element) {
31 | href = $(item.element).find('img').attr('src');
32 | }
33 |
34 | if (!href && item.type === 'image' && item.href) {
35 | href = item.href;
36 | }
37 |
38 | return href;
39 | }
40 | },
41 |
42 | wrap : null,
43 | list : null,
44 | width : 0,
45 |
46 | init: function (opts, obj) {
47 | var that = this,
48 | list,
49 | thumbWidth = opts.width,
50 | thumbHeight = opts.height,
51 | thumbSource = opts.source;
52 |
53 | //Build list structure
54 | list = '';
55 |
56 | for (var n = 0; n < obj.group.length; n++) {
57 | list += '';
58 | }
59 |
60 | this.wrap = $('').addClass(opts.position).appendTo('body');
61 | this.list = $('').appendTo(this.wrap);
62 |
63 | //Load each thumbnail
64 | $.each(obj.group, function (i) {
65 | var href = thumbSource( obj.group[ i ] );
66 |
67 | if (!href) {
68 | return;
69 | }
70 |
71 | $("
").load(function () {
72 | var width = this.width,
73 | height = this.height,
74 | widthRatio, heightRatio, parent;
75 |
76 | if (!that.list || !width || !height) {
77 | return;
78 | }
79 |
80 | //Calculate thumbnail width/height and center it
81 | widthRatio = width / thumbWidth;
82 | heightRatio = height / thumbHeight;
83 |
84 | parent = that.list.children().eq(i).find('a');
85 |
86 | if (widthRatio >= 1 && heightRatio >= 1) {
87 | if (widthRatio > heightRatio) {
88 | width = Math.floor(width / heightRatio);
89 | height = thumbHeight;
90 |
91 | } else {
92 | width = thumbWidth;
93 | height = Math.floor(height / widthRatio);
94 | }
95 | }
96 |
97 | $(this).css({
98 | width : width,
99 | height : height,
100 | top : Math.floor(thumbHeight / 2 - height / 2),
101 | left : Math.floor(thumbWidth / 2 - width / 2)
102 | });
103 |
104 | parent.width(thumbWidth).height(thumbHeight);
105 |
106 | $(this).hide().appendTo(parent).fadeIn(300);
107 |
108 | }).attr('src', href);
109 | });
110 |
111 | //Set initial width
112 | this.width = this.list.children().eq(0).outerWidth(true);
113 |
114 | this.list.width(this.width * (obj.group.length + 1)).css('left', Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5)));
115 | },
116 |
117 | beforeLoad: function (opts, obj) {
118 | //Remove self if gallery do not have at least two items
119 | if (obj.group.length < 2) {
120 | obj.helpers.thumbs = false;
121 |
122 | return;
123 | }
124 |
125 | //Increase bottom margin to give space for thumbs
126 | obj.margin[ opts.position === 'top' ? 0 : 2 ] += ((opts.height) + 15);
127 | },
128 |
129 | afterShow: function (opts, obj) {
130 | //Check if exists and create or update list
131 | if (this.list) {
132 | this.onUpdate(opts, obj);
133 |
134 | } else {
135 | this.init(opts, obj);
136 | }
137 |
138 | //Set active element
139 | this.list.children().removeClass('active').eq(obj.index).addClass('active');
140 | },
141 |
142 | //Center list
143 | onUpdate: function (opts, obj) {
144 | if (this.list) {
145 | this.list.stop(true).animate({
146 | 'left': Math.floor($(window).width() * 0.5 - (obj.index * this.width + this.width * 0.5))
147 | }, 150);
148 | }
149 | },
150 |
151 | beforeClose: function () {
152 | if (this.wrap) {
153 | this.wrap.remove();
154 | }
155 |
156 | this.wrap = null;
157 | this.list = null;
158 | this.width = 0;
159 | }
160 | }
161 |
162 | }(jQuery));
--------------------------------------------------------------------------------
/assets/css/plugins/fancybox/jquery.fancybox.css:
--------------------------------------------------------------------------------
1 | /*! fancyBox v2.1.4 fancyapps.com | fancyapps.com/fancybox/#license */
2 | .fancybox-wrap,
3 | .fancybox-skin,
4 | .fancybox-outer,
5 | .fancybox-inner,
6 | .fancybox-image,
7 | .fancybox-wrap iframe,
8 | .fancybox-wrap object,
9 | .fancybox-nav,
10 | .fancybox-nav span,
11 | .fancybox-tmp
12 | {
13 | padding: 0;
14 | margin: 0;
15 | border: 0;
16 | outline: none;
17 | vertical-align: top;
18 | }
19 |
20 | .fancybox-wrap {
21 | position: absolute;
22 | top: 0;
23 | left: 0;
24 | z-index: 8020;
25 | }
26 |
27 | .fancybox-skin {
28 | position: relative;
29 | background: #f9f9f9;
30 | color: #444;
31 | text-shadow: none;
32 | -webkit-border-radius: 4px;
33 | -moz-border-radius: 4px;
34 | border-radius: 4px;
35 | }
36 |
37 | .fancybox-opened {
38 | z-index: 8030;
39 | }
40 |
41 | .fancybox-opened .fancybox-skin {
42 | -webkit-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
43 | -moz-box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
44 | box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
45 | }
46 |
47 | .fancybox-outer, .fancybox-inner {
48 | position: relative;
49 | }
50 |
51 | .fancybox-inner {
52 | overflow: hidden;
53 | }
54 |
55 | .fancybox-type-iframe .fancybox-inner {
56 | -webkit-overflow-scrolling: touch;
57 | }
58 |
59 | .fancybox-error {
60 | color: #444;
61 | font: 14px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
62 | margin: 0;
63 | padding: 15px;
64 | white-space: nowrap;
65 | }
66 |
67 | .fancybox-image, .fancybox-iframe {
68 | display: block;
69 | width: 100%;
70 | height: 100%;
71 | }
72 |
73 | .fancybox-image {
74 | max-width: 100%;
75 | max-height: 100%;
76 | }
77 |
78 | #fancybox-loading, .fancybox-close, .fancybox-prev span, .fancybox-next span {
79 | background-image: url('fancybox_sprite.png');
80 | }
81 |
82 | #fancybox-loading {
83 | position: fixed;
84 | top: 50%;
85 | left: 50%;
86 | margin-top: -22px;
87 | margin-left: -22px;
88 | background-position: 0 -108px;
89 | opacity: 0.8;
90 | cursor: pointer;
91 | z-index: 8060;
92 | }
93 |
94 | #fancybox-loading div {
95 | width: 44px;
96 | height: 44px;
97 | background: url('fancybox_loading.gif') center center no-repeat;
98 | }
99 |
100 | .fancybox-close {
101 | position: absolute;
102 | top: -18px;
103 | right: -18px;
104 | width: 36px;
105 | height: 36px;
106 | cursor: pointer;
107 | z-index: 8040;
108 | }
109 |
110 | .fancybox-nav {
111 | position: absolute;
112 | top: 0;
113 | width: 40%;
114 | height: 100%;
115 | cursor: pointer;
116 | text-decoration: none;
117 | background: transparent url('blank.gif'); /* helps IE */
118 | -webkit-tap-highlight-color: rgba(0,0,0,0);
119 | z-index: 8040;
120 | }
121 |
122 | .fancybox-prev {
123 | left: 0;
124 | }
125 |
126 | .fancybox-next {
127 | right: 0;
128 | }
129 |
130 | .fancybox-nav span {
131 | position: absolute;
132 | top: 50%;
133 | width: 36px;
134 | height: 34px;
135 | margin-top: -18px;
136 | cursor: pointer;
137 | z-index: 8040;
138 | visibility: hidden;
139 | }
140 |
141 | .fancybox-prev span {
142 | left: 10px;
143 | background-position: 0 -36px;
144 | }
145 |
146 | .fancybox-next span {
147 | right: 10px;
148 | background-position: 0 -72px;
149 | }
150 |
151 | .fancybox-nav:hover span {
152 | visibility: visible;
153 | }
154 |
155 | .fancybox-tmp {
156 | position: absolute;
157 | top: -99999px;
158 | left: -99999px;
159 | visibility: hidden;
160 | max-width: 99999px;
161 | max-height: 99999px;
162 | overflow: visible !important;
163 | }
164 |
165 | /* Overlay helper */
166 |
167 | .fancybox-lock {
168 | overflow: hidden;
169 | }
170 |
171 | .fancybox-overlay {
172 | position: absolute;
173 | top: 0;
174 | left: 0;
175 | overflow: hidden;
176 | display: none;
177 | z-index: 8010;
178 | background: url('fancybox_overlay.png');
179 | }
180 |
181 | .fancybox-overlay-fixed {
182 | position: fixed;
183 | bottom: 0;
184 | right: 0;
185 | }
186 |
187 | .fancybox-lock .fancybox-overlay {
188 | overflow: auto;
189 | overflow-y: scroll;
190 | }
191 |
192 | /* Title helper */
193 |
194 | .fancybox-title {
195 | visibility: hidden;
196 | font: normal 13px/20px "Helvetica Neue",Helvetica,Arial,sans-serif;
197 | position: relative;
198 | text-shadow: none;
199 | z-index: 8050;
200 | }
201 |
202 | .fancybox-opened .fancybox-title {
203 | visibility: visible;
204 | }
205 |
206 | .fancybox-title-float-wrap {
207 | position: absolute;
208 | bottom: 0;
209 | right: 50%;
210 | margin-bottom: -35px;
211 | z-index: 8050;
212 | text-align: center;
213 | }
214 |
215 | .fancybox-title-float-wrap .child {
216 | display: inline-block;
217 | margin-right: -100%;
218 | padding: 2px 20px;
219 | background: transparent; /* Fallback for web browsers that doesn't support RGBa */
220 | background: rgba(0, 0, 0, 0.8);
221 | -webkit-border-radius: 15px;
222 | -moz-border-radius: 15px;
223 | border-radius: 15px;
224 | text-shadow: 0 1px 2px #222;
225 | color: #FFF;
226 | font-weight: bold;
227 | line-height: 24px;
228 | white-space: nowrap;
229 | }
230 |
231 | .fancybox-title-outside-wrap {
232 | position: relative;
233 | margin-top: 10px;
234 | color: #fff;
235 | }
236 |
237 | .fancybox-title-inside-wrap {
238 | padding-top: 10px;
239 | }
240 |
241 | .fancybox-title-over-wrap {
242 | position: absolute;
243 | bottom: 0;
244 | left: 0;
245 | color: #fff;
246 | padding: 10px;
247 | background: #000;
248 | background: rgba(0, 0, 0, .8);
249 | }
--------------------------------------------------------------------------------
/assets/css/style.css:
--------------------------------------------------------------------------------
1 | /* Шрифты */
2 | @import url('http://fonts.googleapis.com/css?family=PT+Sans:400,700&subset=latin,cyrillic');
3 | @import url('../fonts/grand.css');
4 | /* Normalize */
5 | /* normalize.css v3.0.0 | MIT License | git.io/normalize */
6 | html
7 | {
8 | font-family: sans-serif;
9 |
10 | -ms-text-size-adjust: 100%;
11 | -webkit-text-size-adjust: 100%;
12 | }
13 | body
14 | {
15 | margin: 0;
16 | }
17 | article,
18 | aside,
19 | details,
20 | figcaption,
21 | figure,
22 | footer,
23 | header,
24 | hgroup,
25 | main,
26 | nav,
27 | section,
28 | summary
29 | {
30 | display: block;
31 | }
32 | audio,
33 | canvas,
34 | progress,
35 | video
36 | {
37 | display: inline-block;
38 |
39 | vertical-align: baseline;
40 | }
41 | audio:not([controls])
42 | {
43 | display: none;
44 |
45 | height: 0;
46 | }
47 | [hidden],
48 | template
49 | {
50 | display: none;
51 | }
52 | a
53 | {
54 | background: transparent;
55 | }
56 | a:active,
57 | a:hover
58 | {
59 | outline: 0;
60 | }
61 | abbr[title]
62 | {
63 | border-bottom: 1px dotted;
64 | }
65 | b,
66 | strong
67 | {
68 | font-weight: bold;
69 | }
70 | dfn
71 | {
72 | font-style: italic;
73 | }
74 | h1
75 | {
76 | font-size: 2em;
77 |
78 | margin: .67em 0;
79 | }
80 | mark
81 | {
82 | color: #000;
83 | background: #ff0;
84 | }
85 | small
86 | {
87 | font-size: 80%;
88 | }
89 | sub,
90 | sup
91 | {
92 | font-size: 75%;
93 | line-height: 0;
94 |
95 | position: relative;
96 |
97 | vertical-align: baseline;
98 | }
99 | sup
100 | {
101 | top: -.5em;
102 | }
103 | sub
104 | {
105 | bottom: -.25em;
106 | }
107 | img
108 | {
109 | border: 0;
110 | }
111 | svg:not(:root)
112 | {
113 | overflow: hidden;
114 | }
115 | figure
116 | {
117 | margin: 1em 40px;
118 | }
119 | hr
120 | {
121 | -moz-box-sizing: content-box;
122 | box-sizing: content-box;
123 | height: 0;
124 | }
125 | pre
126 | {
127 | overflow: auto;
128 | }
129 | code,
130 | kbd,
131 | pre,
132 | samp
133 | {
134 | font-family: monospace, monospace;
135 | font-size: 1em;
136 | }
137 | button,
138 | input,
139 | optgroup,
140 | select,
141 | textarea
142 | {
143 | font: inherit;
144 |
145 | margin: 0;
146 |
147 | color: inherit;
148 | }
149 | button
150 | {
151 | overflow: visible;
152 | }
153 | button,
154 | select
155 | {
156 | text-transform: none;
157 | }
158 | button,
159 | html input[type='button'],
160 | input[type='reset'],
161 | input[type='submit']
162 | {
163 | cursor: pointer;
164 |
165 | -webkit-appearance: button;
166 | }
167 | button[disabled],
168 | html input[disabled]
169 | {
170 | cursor: default;
171 | }
172 | button::-moz-focus-inner,
173 | input::-moz-focus-inner
174 | {
175 | padding: 0;
176 |
177 | border: 0;
178 | }
179 | input
180 | {
181 | line-height: normal;
182 | }
183 | input[type='checkbox'],
184 | input[type='radio']
185 | {
186 | box-sizing: border-box;
187 | padding: 0;
188 | }
189 | input[type='number']::-webkit-inner-spin-button,
190 | input[type='number']::-webkit-outer-spin-button
191 | {
192 | height: auto;
193 | }
194 | input[type='search']
195 | {
196 | -webkit-box-sizing: content-box;
197 | -moz-box-sizing: content-box;
198 | box-sizing: content-box;
199 |
200 | -webkit-appearance: textfield;
201 | }
202 | input[type='search']::-webkit-search-cancel-button,
203 | input[type='search']::-webkit-search-decoration
204 | {
205 | -webkit-appearance: none;
206 | }
207 | fieldset
208 | {
209 | margin: 0 2px;
210 | padding: .35em .625em .75em;
211 |
212 | border: 1px solid #c0c0c0;
213 | }
214 | legend
215 | {
216 | padding: 0;
217 |
218 | border: 0;
219 | }
220 | textarea
221 | {
222 | overflow: auto;
223 | }
224 | optgroup
225 | {
226 | font-weight: bold;
227 | }
228 | table
229 | {
230 | border-spacing: 0;
231 | border-collapse: collapse;
232 | }
233 | td,
234 | th
235 | {
236 | padding: 0;
237 | }
238 | /* Глобальные стили */
239 | *
240 | {
241 | -webkit-box-sizing: border-box;
242 | -moz-box-sizing: border-box;
243 | box-sizing: border-box;
244 | }
245 | .g-clf:after,
246 | .g-clf:before
247 | {
248 | display: table;
249 | clear: both;
250 |
251 | content: '';
252 | }
253 | /* Обвязка */
254 | html,
255 | body
256 | {
257 | font: normal 16px 'PT Sans', Verdana, Tahoma;
258 |
259 | height: 100%;
260 | }
261 | body
262 | {
263 | background: #bdc3c7;
264 | }
265 | body.welcome
266 | {
267 | background: url('../img/page/blur.jpg') no-repeat 0 0;
268 | -webkit-background-size: cover;
269 | -moz-background-size: cover;
270 | background-size: cover;
271 |
272 | -ms-background-size: cover;
273 | }
274 | body .auth
275 | {
276 | position: absolute;
277 | top: 50%;
278 | left: 50%;
279 |
280 | display: block;
281 |
282 | width: 200px;
283 | height: 29px;
284 | margin-left: -100px;
285 |
286 | cursor: pointer;
287 | text-indent: -9999px;
288 |
289 | outline: none;
290 | background: url('../img/page/auth.png') no-repeat 0 0;
291 | }
292 | body .auth:hover
293 | {
294 | background: url('../img/page/auth_h.png') no-repeat 0 0;
295 | }
296 | .page
297 | {
298 | position: relative;
299 |
300 | min-height: 100%;
301 | margin: 0 auto;
302 | }
303 | /* Шапка */
304 | .header
305 | {
306 | position: fixed;
307 | z-index: 9999;
308 | top: 0;
309 | left: 0;
310 |
311 | width: 100%;
312 | height: 50px;
313 |
314 | background: #17b287;
315 | -webkit-box-shadow: 0 1px 1px 2px rgba(0,0,0,.5);
316 | -moz-box-shadow: 0 1px 1px 2px rgba(0,0,0,.5);
317 | box-shadow: 0 1px 1px 2px rgba(0,0,0,.5);
318 | }
319 | /* Menu */
320 | .menu
321 | {
322 | margin: 0;
323 | padding: 14px 0 0;
324 |
325 | list-style: none;
326 |
327 | text-align: center;
328 | }
329 | .menu__item
330 | {
331 | display: inline-block;
332 |
333 | margin-right: 15px;
334 |
335 | cursor: pointer;
336 | }
337 | .menu__item:last-child
338 | {
339 | margin-right: 0;
340 | }
341 | .menu__link
342 | {
343 | padding: 5px 20px;
344 |
345 | -webkit-transition: color .5s ease;
346 | -moz-transition: color .5s ease;
347 | transition: color .5s ease;
348 | text-decoration: none;
349 |
350 | color: #17b287;
351 | background: #f9f9f9;
352 | }
353 | .menu__link:hover
354 | {
355 | color: #ff4c4b;
356 | }
357 | /* Основной контент */
358 | .main
359 | {
360 | margin: 0 auto;
361 | padding: 50px 10px 115px;
362 | }
363 | /* Боковое меню */
364 | /* Подвал */
365 | .footer
366 | {
367 | position: absolute;
368 | bottom: 0;
369 |
370 | width: 100%;
371 | height: 89px;
372 |
373 | border-top: 1px solid #4f4f50;
374 | border-bottom: 1px solid #4f4f50;
375 | background: #444;
376 | }
377 | .footer__copyright
378 | {
379 | font: normal .75em 'Tahoma', Arial, Verdana;
380 |
381 | float: right;
382 |
383 | margin: 38px 60px 0 0;
384 |
385 | color: #dddbdb;
386 | }
387 | /* Форма */
388 | .form
389 | {
390 | position: relative;
391 |
392 | width: 605px;
393 | }
394 | .form__field
395 | {
396 | margin: 0;
397 | padding: 0;
398 |
399 | border: 0;
400 | }
401 | .form__label
402 | {
403 | display: block;
404 |
405 | padding: 5px 0;
406 | }
407 | .form__label-title
408 | {
409 | display: inline-block;
410 |
411 | width: 200px;
412 |
413 | vertical-align: top;
414 | }
415 | .form__input,
416 | .form__select,
417 | .form__textarea
418 | {
419 | font-size: .875em;
420 |
421 | width: 400px;
422 |
423 | border: 1px solid #a0a0a0;
424 | outline: none;
425 | }
426 | .form__input
427 | {
428 | height: 30px;
429 | }
430 | .form__input,
431 | .form__textarea
432 | {
433 | padding: 0 5px;
434 | }
435 | .form__input:focus,
436 | .form__textarea:focus
437 | {
438 | -webkit-box-shadow: 0 0 2px 2px #ffe500;
439 | -moz-box-shadow: 0 0 2px 2px #ffe500;
440 | box-shadow: 0 0 2px 2px #ffe500;
441 | }
442 | .form__select
443 | {
444 | width: 200px;
445 | }
446 | .form__textarea
447 | {
448 | padding: 3px 5px;
449 |
450 | resize: vertical;
451 | }
452 | .form__answer
453 | {
454 | display: inline-block;
455 |
456 | width: 400px;
457 | }
458 | .form__radio-wrapper
459 | {
460 | display: block;
461 | }
462 | /* Сетка */
463 | .grid
464 | {
465 | display: block;
466 | }
467 | /* Строка сетки */
468 | .row
469 | {
470 | margin-bottom: 15px;
471 | }
472 | /* Колонка сетки */
473 | [class*='column_xs-']
474 | {
475 | float: left;
476 | }
477 | .column
478 | {
479 | position: relative;
480 |
481 | min-height: 1px;
482 | padding-right: 10px;
483 | padding-left: 10px;
484 | }
485 | .column_xs-1
486 | {
487 | width: 8.333333333333334%;
488 | }
489 | .column_xs-2
490 | {
491 | width: 16.666666666666668%;
492 | }
493 | .column_xs-3
494 | {
495 | width: 25%;
496 | }
497 | .column_xs-4
498 | {
499 | width: 33.333333333333336%;
500 | }
501 | .column_xs-5
502 | {
503 | width: 41.66666666666667%;
504 | }
505 | .column_xs-6
506 | {
507 | width: 50%;
508 | }
509 | .column_xs-7
510 | {
511 | width: 58.333333333333336%;
512 | }
513 | .column_xs-8
514 | {
515 | width: 66.66666666666667%;
516 | }
517 | .column_xs-9
518 | {
519 | width: 75%;
520 | }
521 | .column_xs-10
522 | {
523 | width: 83.33333333333334%;
524 | }
525 | .column_xs-11
526 | {
527 | width: 91.66666666666667%;
528 | }
529 | .column_xs-12
530 | {
531 | width: 100%;
532 | }
533 | .column__offset_xs-1
534 | {
535 | margin-left: 8.333333333333334%;
536 | }
537 | .column__offset_xs-2
538 | {
539 | margin-left: 16.666666666666668%;
540 | }
541 | .column__offset_xs-3
542 | {
543 | margin-left: 25%;
544 | }
545 | .column__offset_xs-4
546 | {
547 | margin-left: 33.333333333333336%;
548 | }
549 | .column__offset_xs-5
550 | {
551 | margin-left: 41.66666666666667%;
552 | }
553 | .column__offset_xs-6
554 | {
555 | margin-left: 50%;
556 | }
557 | .column__offset_xs-7
558 | {
559 | margin-left: 58.333333333333336%;
560 | }
561 | .column__offset_xs-8
562 | {
563 | margin-left: 66.66666666666667%;
564 | }
565 | .column__offset_xs-9
566 | {
567 | margin-left: 75%;
568 | }
569 | .column__offset_xs-10
570 | {
571 | margin-left: 83.33333333333334%;
572 | }
573 | .column__offset_xs-11
574 | {
575 | margin-left: 91.66666666666667%;
576 | }
577 | .column__offset_xs-12
578 | {
579 | margin-left: 100%;
580 | }
581 | /* Profile */
582 | .profile
583 | {
584 | margin: 40px 0 0;
585 | }
586 | .profile__photo
587 | {
588 | display: block;
589 |
590 | width: 150px;
591 | height: 150px;
592 | margin: 0 auto;
593 | }
594 | .profile__username
595 | {
596 | font: bold 2em;
597 | line-height: 20px;
598 |
599 | margin: 10px 0 0;
600 |
601 | text-align: center;
602 |
603 | color: #fff;
604 | text-shadow: 0 1px 2px #333;
605 | }
606 | .profile__stats,
607 | .profile__info
608 | {
609 | margin: 20px 0 30px;
610 | padding: 0;
611 |
612 | list-style: none;
613 |
614 | text-align: center;
615 | }
616 | .profile__item
617 | {
618 | font: normal 1.25em;
619 |
620 | display: inline-block;
621 |
622 | padding: 0 20px;
623 |
624 | text-align: center;
625 |
626 | color: #fff;
627 | text-shadow: 0 1px 1px #333;
628 | }
629 | .profile__item a
630 | {
631 | -webkit-transition: color .5s ease;
632 | -moz-transition: color .5s ease;
633 | transition: color .5s ease;
634 | text-decoration: none;
635 |
636 | color: #fff;
637 | text-shadow: 0 1px 1px #333;
638 | }
639 | .profile__item a:hover
640 | {
641 | color: #17b287;
642 | }
643 | .profile__info .profile__item
644 | {
645 | display: block;
646 |
647 | text-align: center;
648 |
649 | color: #333;
650 | text-shadow: none;
651 | }
652 | /* Popular */
653 | .search
654 | {
655 | margin: 40px 0 0;
656 | }
657 | .search__form
658 | {
659 | width: 100%;
660 | height: 60px;
661 | margin: 0 auto 30px;
662 | }
663 | .search__input
664 | {
665 | font: normal 24px 'Roboto Condensed';
666 |
667 | display: inline-block;
668 |
669 | width: 100%;
670 | height: 60px;
671 | padding: 0 14px;
672 |
673 | color: #bdbab4;
674 | border: 0;
675 | outline: none;
676 | }
677 | /* Photo List */
678 | .photo-list
679 | {
680 | margin: 0;
681 | padding: 0;
682 |
683 | list-style: none;
684 | }
685 | .photo-list__item
686 | {
687 | display: inline-block;
688 |
689 | width: 20.5%;
690 | margin: 0 6% 6% 0;
691 |
692 | cursor: pointer;
693 | }
694 | .photo-list__item:nth-child(4n)
695 | {
696 | margin-right: 0;
697 | }
698 | .photo-list__item img
699 | {
700 | max-width: 100%;
701 |
702 | -webkit-box-shadow: 0 0 2px 3px rgba(0,0,0,.7);
703 | -moz-box-shadow: 0 0 2px 3px rgba(0,0,0,.7);
704 | box-shadow: 0 0 2px 3px rgba(0,0,0,.7);
705 | }
706 | .photo-list__likes
707 | {
708 | font-size: .7em;
709 |
710 | float: right;
711 |
712 | color: #333;
713 | }
714 | .photo-list__likes:hover
715 | {
716 | text-decoration: underline;
717 | }
718 | /* About page */
719 | .about
720 | {
721 | padding-top: 40px;
722 |
723 | text-align: center;
724 | }
725 | .about__header
726 | {
727 | font: bold 2em 'Roboto Condensed', Arial, Tahoma;
728 |
729 | color: #fff;
730 | text-shadow: 0 1px 1px #333;
731 | }
732 | .about__text
733 | {
734 | color: #333;
735 | text-shadow: 0 1px 1px #fff;
736 | }
737 | .about__text a
738 | {
739 | -webkit-transition: border-color .5s ease;
740 | -moz-transition: border-color .5s ease;
741 | transition: border-color .5s ease;
742 | text-decoration: none;
743 |
744 | color: #333;
745 | border-bottom: 1px dashed #27ae60;
746 | }
747 | .about__text a:hover
748 | {
749 | border-color: #ff4c4b;
750 | }
751 | /* Social Icons */
752 | .social
753 | {
754 | float: left;
755 |
756 | margin: 32px 0 0 60px;
757 | padding: 0;
758 |
759 | list-style: none;
760 | }
761 | .social__item
762 | {
763 | display: inline-block;
764 | float: left;
765 |
766 | margin-left: 15px;
767 | }
768 | .social__item:first-child
769 | {
770 | margin-left: 0;
771 | }
772 | .social__link
773 | {
774 | font: normal 24px 'Arial', Tahoma, Verdana;
775 |
776 | -webkit-transition: color .4s ease;
777 | -moz-transition: color .4s ease;
778 | transition: color .4s ease;
779 | text-decoration: none;
780 | text-indent: -9999px;
781 |
782 | color: #dddbdb;
783 | }
784 | .social__link:hover
785 | {
786 | color: #27ae60;
787 | }
788 | /* Feed */
789 | .feed
790 | {
791 | width: 95%;
792 | margin: 2% auto 0;
793 | padding: 0;
794 |
795 | list-style: none;
796 | }
797 | .feed__item
798 | {
799 | display: block;
800 |
801 | width: 76%;
802 | min-height: 400px;
803 | margin: 40px auto 0;
804 | }
805 | /* User in Feed */
806 | .user
807 | {
808 | margin-bottom: 10px;
809 | }
810 | .user__pic
811 | {
812 | float: left;
813 |
814 | width: 100px;
815 | height: 100px;
816 | margin-right: 20px;
817 | }
818 | .user__pic img
819 | {
820 | width: 100px;
821 |
822 | border-radius: 50%;
823 | }
824 | .user__name
825 | {
826 | display: block;
827 |
828 | color: #333;
829 | }
830 | .user__likes
831 | {
832 | display: block;
833 |
834 | height: 80px;
835 | }
836 | .user__like
837 | {
838 | display: inline-block;
839 |
840 | width: 80px;
841 | height: 80px;
842 |
843 | cursor: pointer;
844 | vertical-align: middle;
845 |
846 | background: url('data:image/png;base64,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') no-repeat 0 0;
847 | }
848 | .user__like:hover,
849 | .user__like_liked
850 | {
851 | background-position: 0 -80px;
852 | }
853 | .user__likes-count
854 | {
855 | font-size: 2.5em;
856 |
857 | position: relative;
858 |
859 | display: inline-block;
860 |
861 | vertical-align: middle;
862 | }
863 | .user__video
864 | {
865 | display: block;
866 |
867 | width: 100px;
868 | height: 100px;
869 |
870 | cursor: pointer;
871 |
872 | background: url('../img/user/video-play.png');
873 | }
874 | /* Photo in Feed */
875 | .photo
876 | {
877 | overflow: hidden;
878 | }
879 | .photo__pic
880 | {
881 | display: block;
882 |
883 | width: 500px;
884 | max-width: 100%;
885 | margin-left: 100px;
886 | }
887 | /* Comments in Feed */
888 | .comments
889 | {
890 | overflow: hidden;
891 |
892 | margin: 10px 0 0 100px;
893 | padding: 0;
894 |
895 | list-style: none;
896 | }
897 | .comments__item
898 | {
899 | display: block;
900 |
901 | margin: 0 0 5px 0;
902 | }
903 | .comments__pic
904 | {
905 | float: left;
906 |
907 | width: 20px;
908 | margin-right: 5px;
909 | }
910 | .comments__username
911 | {
912 | font-size: .85em;
913 | font-weight: bold;
914 |
915 | text-decoration: none;
916 |
917 | color: #444;
918 | }
919 | .comments__username:hover
920 | {
921 | border-bottom: 1px dashed #444;
922 | }
923 | .comments__text
924 | {
925 | font-size: .85em;
926 | }
927 | /* Followers and Follows */
928 | .follow__header
929 | {
930 | font-size: 2em;
931 | font-weight: 700;
932 |
933 | margin: 20px 0;
934 |
935 | text-align: center;
936 |
937 | color: #fff;
938 | text-shadow: 0 1px 1px #333;
939 | }
940 | .follow__list
941 | {
942 | margin: 0;
943 | padding: 0;
944 |
945 | list-style: none;
946 | }
947 | .follow__item
948 | {
949 | float: left;
950 |
951 | width: 100%;
952 | height: 100px;
953 | margin: 0;
954 |
955 | vertical-align: top;
956 |
957 | border-right: 1px solid #17b287;
958 | border-bottom: 1px solid #17b287;
959 | border-left: 1px solid #17b287;
960 | background: #fff;
961 | }
962 | .follow__item:first-child
963 | {
964 | border-top: 1px solid #17b287;
965 | }
966 | .follow__item:nth-child(4n)
967 | {
968 | margin-right: 0;
969 | }
970 | .follow__item a
971 | {
972 | font-size: 1.25em;
973 | font-weight: bold;
974 |
975 | text-align: center;
976 | text-decoration: none;
977 |
978 | color: #333;
979 | }
980 | .follow__avatar
981 | {
982 | display: inline-block;
983 | float: left;
984 |
985 | width: 99px;
986 | margin-right: 10px;
987 | }
988 | .follow__username
989 | {
990 | position: relative;
991 | top: 35px;
992 |
993 | overflow: hidden;
994 |
995 | -webkit-transition: color .5s ease;
996 | -moz-transition: color .5s ease;
997 | transition: color .5s ease;
998 | }
999 | .follow__username:hover
1000 | {
1001 | color: #ff4c4b;
1002 | }
1003 | .follow__btn
1004 | {
1005 | float: right;
1006 |
1007 | margin: 35px 10px 0 0;
1008 | padding: 3px 10px;
1009 |
1010 | color: #fff;
1011 | border: 0;
1012 | background: #ff4c4b;
1013 | -webkit-box-shadow: 2px 2px 2px 1px rgba(0,0,0,.5);
1014 | -moz-box-shadow: 2px 2px 2px 1px rgba(0,0,0,.5);
1015 | box-shadow: 2px 2px 2px 1px rgba(0,0,0,.5);
1016 | }
1017 | .follow__btn_read
1018 | {
1019 | background: #27ae60;
1020 | }
1021 | /* Всплывающие окна */
1022 | /* Responsive */
1023 | @media (min-width: 768px)
1024 | {
1025 | [class*='column_sm-']
1026 | {
1027 | float: left;
1028 | }
1029 | .column_sm-1
1030 | {
1031 | width: 8.333333333333334%;
1032 | }
1033 | .column_sm-2
1034 | {
1035 | width: 16.666666666666668%;
1036 | }
1037 | .column_sm-3
1038 | {
1039 | width: 25%;
1040 | }
1041 | .column_sm-4
1042 | {
1043 | width: 33.333333333333336%;
1044 | }
1045 | .column_sm-5
1046 | {
1047 | width: 41.66666666666667%;
1048 | }
1049 | .column_sm-6
1050 | {
1051 | width: 50%;
1052 | }
1053 | .column_sm-7
1054 | {
1055 | width: 58.333333333333336%;
1056 | }
1057 | .column_sm-8
1058 | {
1059 | width: 66.66666666666667%;
1060 | }
1061 | .column_sm-9
1062 | {
1063 | width: 75%;
1064 | }
1065 | .column_sm-10
1066 | {
1067 | width: 83.33333333333334%;
1068 | }
1069 | .column_sm-11
1070 | {
1071 | width: 91.66666666666667%;
1072 | }
1073 | .column_sm-12
1074 | {
1075 | width: 100%;
1076 | }
1077 | .column__offset_sm-1
1078 | {
1079 | margin-left: 8.333333333333334%;
1080 | }
1081 | .column__offset_sm-2
1082 | {
1083 | margin-left: 16.666666666666668%;
1084 | }
1085 | .column__offset_sm-3
1086 | {
1087 | margin-left: 25%;
1088 | }
1089 | .column__offset_sm-4
1090 | {
1091 | margin-left: 33.333333333333336%;
1092 | }
1093 | .column__offset_sm-5
1094 | {
1095 | margin-left: 41.66666666666667%;
1096 | }
1097 | .column__offset_sm-6
1098 | {
1099 | margin-left: 50%;
1100 | }
1101 | .column__offset_sm-7
1102 | {
1103 | margin-left: 58.333333333333336%;
1104 | }
1105 | .column__offset_sm-8
1106 | {
1107 | margin-left: 66.66666666666667%;
1108 | }
1109 | .column__offset_sm-9
1110 | {
1111 | margin-left: 75%;
1112 | }
1113 | .column__offset_sm-10
1114 | {
1115 | margin-left: 83.33333333333334%;
1116 | }
1117 | .column__offset_sm-11
1118 | {
1119 | margin-left: 91.66666666666667%;
1120 | }
1121 | .column__offset_sm-12
1122 | {
1123 | margin-left: 100%;
1124 | }
1125 | }
1126 | @media (min-width: 992px)
1127 | {
1128 | .page
1129 | {
1130 | width: 940px;
1131 | }
1132 | [class*='column_md-']
1133 | {
1134 | float: left;
1135 | }
1136 | .column_md-1
1137 | {
1138 | width: 8.333333333333334%;
1139 | }
1140 | .column_md-2
1141 | {
1142 | width: 16.666666666666668%;
1143 | }
1144 | .column_md-3
1145 | {
1146 | width: 25%;
1147 | }
1148 | .column_md-4
1149 | {
1150 | width: 33.333333333333336%;
1151 | }
1152 | .column_md-5
1153 | {
1154 | width: 41.66666666666667%;
1155 | }
1156 | .column_md-6
1157 | {
1158 | width: 50%;
1159 | }
1160 | .column_md-7
1161 | {
1162 | width: 58.333333333333336%;
1163 | }
1164 | .column_md-8
1165 | {
1166 | width: 66.66666666666667%;
1167 | }
1168 | .column_md-9
1169 | {
1170 | width: 75%;
1171 | }
1172 | .column_md-10
1173 | {
1174 | width: 83.33333333333334%;
1175 | }
1176 | .column_md-11
1177 | {
1178 | width: 91.66666666666667%;
1179 | }
1180 | .column_md-12
1181 | {
1182 | width: 100%;
1183 | }
1184 | .column__offset_md-1
1185 | {
1186 | margin-left: 8.333333333333334%;
1187 | }
1188 | .column__offset_md-2
1189 | {
1190 | margin-left: 16.666666666666668%;
1191 | }
1192 | .column__offset_md-3
1193 | {
1194 | margin-left: 25%;
1195 | }
1196 | .column__offset_md-4
1197 | {
1198 | margin-left: 33.333333333333336%;
1199 | }
1200 | .column__offset_md-5
1201 | {
1202 | margin-left: 41.66666666666667%;
1203 | }
1204 | .column__offset_md-6
1205 | {
1206 | margin-left: 50%;
1207 | }
1208 | .column__offset_md-7
1209 | {
1210 | margin-left: 58.333333333333336%;
1211 | }
1212 | .column__offset_md-8
1213 | {
1214 | margin-left: 66.66666666666667%;
1215 | }
1216 | .column__offset_md-9
1217 | {
1218 | margin-left: 75%;
1219 | }
1220 | .column__offset_md-10
1221 | {
1222 | margin-left: 83.33333333333334%;
1223 | }
1224 | .column__offset_md-11
1225 | {
1226 | margin-left: 91.66666666666667%;
1227 | }
1228 | .column__offset_md-12
1229 | {
1230 | margin-left: 100%;
1231 | }
1232 | }
1233 | @media (min-width: 1170px)
1234 | {
1235 | [class*='column_lg-']
1236 | {
1237 | float: left;
1238 | }
1239 | .column_lg-1
1240 | {
1241 | width: 8.333333333333334%;
1242 | }
1243 | .column_lg-2
1244 | {
1245 | width: 16.666666666666668%;
1246 | }
1247 | .column_lg-3
1248 | {
1249 | width: 25%;
1250 | }
1251 | .column_lg-4
1252 | {
1253 | width: 33.333333333333336%;
1254 | }
1255 | .column_lg-5
1256 | {
1257 | width: 41.66666666666667%;
1258 | }
1259 | .column_lg-6
1260 | {
1261 | width: 50%;
1262 | }
1263 | .column_lg-7
1264 | {
1265 | width: 58.333333333333336%;
1266 | }
1267 | .column_lg-8
1268 | {
1269 | width: 66.66666666666667%;
1270 | }
1271 | .column_lg-9
1272 | {
1273 | width: 75%;
1274 | }
1275 | .column_lg-10
1276 | {
1277 | width: 83.33333333333334%;
1278 | }
1279 | .column_lg-11
1280 | {
1281 | width: 91.66666666666667%;
1282 | }
1283 | .column_lg-12
1284 | {
1285 | width: 100%;
1286 | }
1287 | .column__offset_lg-1
1288 | {
1289 | margin-left: 8.333333333333334%;
1290 | }
1291 | .column__offset_lg-2
1292 | {
1293 | margin-left: 16.666666666666668%;
1294 | }
1295 | .column__offset_lg-3
1296 | {
1297 | margin-left: 25%;
1298 | }
1299 | .column__offset_lg-4
1300 | {
1301 | margin-left: 33.333333333333336%;
1302 | }
1303 | .column__offset_lg-5
1304 | {
1305 | margin-left: 41.66666666666667%;
1306 | }
1307 | .column__offset_lg-6
1308 | {
1309 | margin-left: 50%;
1310 | }
1311 | .column__offset_lg-7
1312 | {
1313 | margin-left: 58.333333333333336%;
1314 | }
1315 | .column__offset_lg-8
1316 | {
1317 | margin-left: 66.66666666666667%;
1318 | }
1319 | .column__offset_lg-9
1320 | {
1321 | margin-left: 75%;
1322 | }
1323 | .column__offset_lg-10
1324 | {
1325 | margin-left: 83.33333333333334%;
1326 | }
1327 | .column__offset_lg-11
1328 | {
1329 | margin-left: 91.66666666666667%;
1330 | }
1331 | .column__offset_lg-12
1332 | {
1333 | margin-left: 100%;
1334 | }
1335 | }
1336 |
--------------------------------------------------------------------------------
/assets/css/style.min.css:
--------------------------------------------------------------------------------
1 | @import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700&subset=latin,cyrillic);@import url(../fonts/grand.css);html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{color:#000;background:#ff0}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{font:inherit;margin:0;color:inherit}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{margin:0 2px;padding:.35em .625em .75em;border:1px solid silver}legend{border:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-spacing:0;border-collapse:collapse}legend,td,th{padding:0}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.g-clf:after,.g-clf:before{display:table;clear:both;content:''}body,html{font:16px 'PT Sans',Verdana,Tahoma;height:100%}body{background:#bdc3c7}body.welcome{background:url(../img/page/blur.jpg) no-repeat 0 0;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover;-ms-background-size:cover}body .auth{position:absolute;top:50%;left:50%;display:block;width:200px;height:29px;margin-left:-100px;cursor:pointer;text-indent:-9999px;outline:none;background:url(../img/page/auth.png) no-repeat 0 0}body .auth:hover{background:url(../img/page/auth_h.png) no-repeat 0 0}.page{position:relative;min-height:100%;margin:0 auto}.header{position:fixed;z-index:9999;top:0;left:0;width:100%;height:50px;background:#17b287;-webkit-box-shadow:0 1px 1px 2px rgba(0,0,0,.5);-moz-box-shadow:0 1px 1px 2px rgba(0,0,0,.5);box-shadow:0 1px 1px 2px rgba(0,0,0,.5)}.menu{margin:0;padding:14px 0 0;list-style:none;text-align:center}.menu__item{display:inline-block;margin-right:15px;cursor:pointer}.menu__item:last-child{margin-right:0}.menu__link{padding:5px 20px;-webkit-transition:color .5s ease;-moz-transition:color .5s ease;transition:color .5s ease;text-decoration:none;color:#17b287;background:#f9f9f9}.menu__link:hover{color:#ff4c4b}.main{margin:0 auto;padding:50px 10px 115px}.footer{position:absolute;bottom:0;width:100%;height:89px;border-top:1px solid #4f4f50;border-bottom:1px solid #4f4f50;background:#444}.footer__copyright{font:.75em 'Tahoma',Arial,Verdana;float:right;margin:38px 60px 0 0;color:#dddbdb}.form{position:relative;width:605px}.form__field{margin:0;padding:0;border:0}.form__label{display:block;padding:5px 0}.form__label-title{display:inline-block;width:200px;vertical-align:top}.form__input{width:400px}.form__input,.form__select,.form__textarea{font-size:.875em;border:1px solid #a0a0a0;outline:none}.form__textarea{width:400px}.form__input{height:30px;padding:0 5px}.form__input:focus,.form__textarea:focus{-webkit-box-shadow:0 0 2px 2px #ffe500;-moz-box-shadow:0 0 2px 2px #ffe500;box-shadow:0 0 2px 2px #ffe500}.form__select{width:200px}.form__textarea{padding:3px 5px;resize:vertical}.form__answer{display:inline-block;width:400px}.form__radio-wrapper,.grid{display:block}.row{margin-bottom:15px}[class*=column_xs-]{float:left}.column{position:relative;min-height:1px;padding-right:10px;padding-left:10px}.column_xs-1{width:8.333333333333334%}.column_xs-2{width:16.666666666666668%}.column_xs-3{width:25%}.column_xs-4{width:33.333333333333336%}.column_xs-5{width:41.66666666666667%}.column_xs-6{width:50%}.column_xs-7{width:58.333333333333336%}.column_xs-8{width:66.66666666666667%}.column_xs-9{width:75%}.column_xs-10{width:83.33333333333334%}.column_xs-11{width:91.66666666666667%}.column_xs-12{width:100%}.column__offset_xs-1{margin-left:8.333333333333334%}.column__offset_xs-2{margin-left:16.666666666666668%}.column__offset_xs-3{margin-left:25%}.column__offset_xs-4{margin-left:33.333333333333336%}.column__offset_xs-5{margin-left:41.66666666666667%}.column__offset_xs-6{margin-left:50%}.column__offset_xs-7{margin-left:58.333333333333336%}.column__offset_xs-8{margin-left:66.66666666666667%}.column__offset_xs-9{margin-left:75%}.column__offset_xs-10{margin-left:83.33333333333334%}.column__offset_xs-11{margin-left:91.66666666666667%}.column__offset_xs-12{margin-left:100%}.profile{margin:40px 0 0}.profile__photo{display:block;width:150px;height:150px;margin:0 auto}.profile__username{font:700 2em;line-height:20px;margin:10px 0 0;text-align:center;color:#fff;text-shadow:0 1px 2px #333}.profile__info,.profile__stats{margin:20px 0 30px;padding:0;list-style:none;text-align:center}.profile__item,.profile__item a{color:#fff;text-shadow:0 1px 1px #333}.profile__item{font:1.25em;display:inline-block;padding:0 20px;text-align:center}.profile__item a{-webkit-transition:color .5s ease;-moz-transition:color .5s ease;transition:color .5s ease;text-decoration:none}.profile__item a:hover{color:#17b287}.profile__info .profile__item{display:block;text-align:center;color:#333;text-shadow:none}.search{margin:40px 0 0}.search__form{width:100%;height:60px;margin:0 auto 30px}.search__input{font:24px 'Roboto Condensed';display:inline-block;width:100%;height:60px;padding:0 14px;color:#bdbab4;border:0;outline:none}.photo-list{margin:0;padding:0;list-style:none}.photo-list__item{display:inline-block;width:20.5%;margin:0 6% 6% 0;cursor:pointer}.photo-list__item:nth-child(4n){margin-right:0}.photo-list__item img{max-width:100%;-webkit-box-shadow:0 0 2px 3px rgba(0,0,0,.7);-moz-box-shadow:0 0 2px 3px rgba(0,0,0,.7);box-shadow:0 0 2px 3px rgba(0,0,0,.7)}.photo-list__likes{font-size:.7em;float:right;color:#333}.photo-list__likes:hover{text-decoration:underline}.about{padding-top:40px;text-align:center}.about__header{font:700 2em 'Roboto Condensed',Arial,Tahoma;color:#fff;text-shadow:0 1px 1px #333}.about__text{color:#333;text-shadow:0 1px 1px #fff}.about__text a{-webkit-transition:border-color .5s ease;-moz-transition:border-color .5s ease;transition:border-color .5s ease;text-decoration:none;color:#333;border-bottom:1px dashed #27ae60}.about__text a:hover{border-color:#ff4c4b}.social{float:left;margin:32px 0 0 60px;padding:0;list-style:none}.social__item{display:inline-block;float:left;margin-left:15px}.social__item:first-child{margin-left:0}.social__link{font:24px 'Arial',Tahoma,Verdana;-webkit-transition:color .4s ease;-moz-transition:color .4s ease;transition:color .4s ease;text-decoration:none;text-indent:-9999px;color:#dddbdb}.social__link:hover{color:#27ae60}.feed{width:95%;margin:2% auto 0;padding:0;list-style:none}.feed__item{display:block;width:76%;min-height:400px;margin:40px auto 0}.user{margin-bottom:10px}.user__pic{float:left;width:100px;height:100px;margin-right:20px}.user__pic img{width:100px;border-radius:50%}.user__name{display:block;color:#333}.user__likes{display:block;height:80px}.user__like{display:inline-block;width:80px;height:80px;cursor:pointer;vertical-align:middle;background:url(data:image/png;base64,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) no-repeat 0 0}.user__like:hover,.user__like_liked{background-position:0 -80px}.user__likes-count{font-size:2.5em;position:relative;display:inline-block;vertical-align:middle}.user__video{display:block;width:100px;height:100px;cursor:pointer;background:url(../img/user/video-play.png)}.photo{overflow:hidden}.photo__pic{display:block;width:500px;max-width:100%;margin-left:100px}.comments{overflow:hidden;margin:10px 0 0 100px;padding:0;list-style:none}.comments__item{display:block;margin:0 0 5px}.comments__pic{float:left;width:20px;margin-right:5px}.comments__username{font-size:.85em;font-weight:700;text-decoration:none;color:#444}.comments__username:hover{border-bottom:1px dashed #444}.comments__text{font-size:.85em}.follow__header{font-size:2em;font-weight:700;margin:20px 0;text-align:center;color:#fff;text-shadow:0 1px 1px #333}.follow__list{margin:0;padding:0;list-style:none}.follow__item{float:left;width:100%;height:100px;margin:0;vertical-align:top;border-right:1px solid #17b287;border-bottom:1px solid #17b287;border-left:1px solid #17b287;background:#fff}.follow__item:first-child{border-top:1px solid #17b287}.follow__item:nth-child(4n){margin-right:0}.follow__item a{font-size:1.25em;font-weight:700;text-align:center;text-decoration:none;color:#333}.follow__avatar{display:inline-block;float:left;width:99px;margin-right:10px}.follow__username{position:relative;top:35px;overflow:hidden;-webkit-transition:color .5s ease;-moz-transition:color .5s ease;transition:color .5s ease}.follow__username:hover{color:#ff4c4b}.follow__btn{float:right;margin:35px 10px 0 0;padding:3px 10px;color:#fff;border:0;background:#ff4c4b;-webkit-box-shadow:2px 2px 2px 1px rgba(0,0,0,.5);-moz-box-shadow:2px 2px 2px 1px rgba(0,0,0,.5);box-shadow:2px 2px 2px 1px rgba(0,0,0,.5)}.follow__btn_read{background:#27ae60}@media (min-width:768px){[class*=column_sm-]{float:left}.column_sm-1{width:8.333333333333334%}.column_sm-2{width:16.666666666666668%}.column_sm-3{width:25%}.column_sm-4{width:33.333333333333336%}.column_sm-5{width:41.66666666666667%}.column_sm-6{width:50%}.column_sm-7{width:58.333333333333336%}.column_sm-8{width:66.66666666666667%}.column_sm-9{width:75%}.column_sm-10{width:83.33333333333334%}.column_sm-11{width:91.66666666666667%}.column_sm-12{width:100%}.column__offset_sm-1{margin-left:8.333333333333334%}.column__offset_sm-2{margin-left:16.666666666666668%}.column__offset_sm-3{margin-left:25%}.column__offset_sm-4{margin-left:33.333333333333336%}.column__offset_sm-5{margin-left:41.66666666666667%}.column__offset_sm-6{margin-left:50%}.column__offset_sm-7{margin-left:58.333333333333336%}.column__offset_sm-8{margin-left:66.66666666666667%}.column__offset_sm-9{margin-left:75%}.column__offset_sm-10{margin-left:83.33333333333334%}.column__offset_sm-11{margin-left:91.66666666666667%}.column__offset_sm-12{margin-left:100%}}@media (min-width:992px){.page{width:940px}[class*=column_md-]{float:left}.column_md-1{width:8.333333333333334%}.column_md-2{width:16.666666666666668%}.column_md-3{width:25%}.column_md-4{width:33.333333333333336%}.column_md-5{width:41.66666666666667%}.column_md-6{width:50%}.column_md-7{width:58.333333333333336%}.column_md-8{width:66.66666666666667%}.column_md-9{width:75%}.column_md-10{width:83.33333333333334%}.column_md-11{width:91.66666666666667%}.column_md-12{width:100%}.column__offset_md-1{margin-left:8.333333333333334%}.column__offset_md-2{margin-left:16.666666666666668%}.column__offset_md-3{margin-left:25%}.column__offset_md-4{margin-left:33.333333333333336%}.column__offset_md-5{margin-left:41.66666666666667%}.column__offset_md-6{margin-left:50%}.column__offset_md-7{margin-left:58.333333333333336%}.column__offset_md-8{margin-left:66.66666666666667%}.column__offset_md-9{margin-left:75%}.column__offset_md-10{margin-left:83.33333333333334%}.column__offset_md-11{margin-left:91.66666666666667%}.column__offset_md-12{margin-left:100%}}@media (min-width:1170px){[class*=column_lg-]{float:left}.column_lg-1{width:8.333333333333334%}.column_lg-2{width:16.666666666666668%}.column_lg-3{width:25%}.column_lg-4{width:33.333333333333336%}.column_lg-5{width:41.66666666666667%}.column_lg-6{width:50%}.column_lg-7{width:58.333333333333336%}.column_lg-8{width:66.66666666666667%}.column_lg-9{width:75%}.column_lg-10{width:83.33333333333334%}.column_lg-11{width:91.66666666666667%}.column_lg-12{width:100%}.column__offset_lg-1{margin-left:8.333333333333334%}.column__offset_lg-2{margin-left:16.666666666666668%}.column__offset_lg-3{margin-left:25%}.column__offset_lg-4{margin-left:33.333333333333336%}.column__offset_lg-5{margin-left:41.66666666666667%}.column__offset_lg-6{margin-left:50%}.column__offset_lg-7{margin-left:58.333333333333336%}.column__offset_lg-8{margin-left:66.66666666666667%}.column__offset_lg-9{margin-left:75%}.column__offset_lg-10{margin-left:83.33333333333334%}.column__offset_lg-11{margin-left:91.66666666666667%}.column__offset_lg-12{margin-left:100%}}
--------------------------------------------------------------------------------
/assets/fonts/fonts/Grands.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/fonts/fonts/Grands.eot
--------------------------------------------------------------------------------
/assets/fonts/fonts/Grands.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/assets/fonts/fonts/Grands.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/fonts/fonts/Grands.ttf
--------------------------------------------------------------------------------
/assets/fonts/fonts/Grands.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/fonts/fonts/Grands.woff
--------------------------------------------------------------------------------
/assets/fonts/grand.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Grands';
3 | src:url('fonts/Grands.eot');
4 | src:url('fonts/Grands.eot?#iefix') format('embedded-opentype'),
5 | url('fonts/Grands.svg#Grands') format('svg'),
6 | url('fonts/Grands.woff') format('woff'),
7 | url('fonts/Grands.ttf') format('truetype');
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 |
12 | /* Use the following CSS code if you want to use data attributes for inserting your icons */
13 | [data-icon]:before {
14 | font-family: 'Grands';
15 | content: attr(data-icon);
16 | speak: none;
17 | font-weight: normal;
18 | -webkit-font-smoothing: antialiased;
19 | }
20 |
21 | /* Use the following CSS code if you want to have a class per icon */
22 | [class^="icon-"]:before, [class*=" icon-"]:before {
23 | font-family: 'Grands';
24 | font-style: normal;
25 | speak: none;
26 | font-weight: normal;
27 | -webkit-font-smoothing: antialiased;
28 | }
29 | .icon-YouTube:before {
30 | content: "\e000";
31 | }
32 | .icon-Yandex:before {
33 | content: "\e001";
34 | }
35 | .icon-Vkontakte:before {
36 | content: "\e002";
37 | }
38 | .icon-VK:before {
39 | content: "\e003";
40 | }
41 | .icon-vimeo:before {
42 | content: "\e004";
43 | }
44 | .icon-twitter:before {
45 | content: "\e005";
46 | }
47 | .icon-tumblr:before {
48 | content: "\e006";
49 | }
50 | .icon-Steam:before {
51 | content: "\e007";
52 | }
53 | .icon-StackOverflow:before {
54 | content: "\e008";
55 | }
56 | .icon-SoundCloud:before {
57 | content: "\e009";
58 | }
59 | .icon-Skype:before {
60 | content: "\e00a";
61 | }
62 | .icon-Share:before {
63 | content: "\e00b";
64 | }
65 | .icon-RSS:before {
66 | content: "\e00c";
67 | }
68 | .icon-Readability:before {
69 | content: "\e00d";
70 | }
71 | .icon-Read-it-Later:before {
72 | content: "\e00e";
73 | }
74 | .icon-Pocket:before {
75 | content: "\e00f";
76 | }
77 | .icon-Pinterest:before {
78 | content: "\e010";
79 | }
80 | .icon-Picasa:before {
81 | content: "\e011";
82 | }
83 | .icon-OpenID:before {
84 | content: "\e012";
85 | }
86 | .icon-MySpace:before {
87 | content: "\e013";
88 | }
89 | .icon-MoiKrug:before {
90 | content: "\e014";
91 | }
92 | .icon-Linked-in:before {
93 | content: "\e015";
94 | }
95 | .icon-LifeJournal:before {
96 | content: "\e016";
97 | }
98 | .icon-lastfm:before {
99 | content: "\e017";
100 | }
101 | .icon-Jabber:before {
102 | content: "\e018";
103 | }
104 | .icon-Instapaper:before {
105 | content: "\e019";
106 | }
107 | .icon-HabraHabr:before {
108 | content: "\e01a";
109 | }
110 | .icon-google:before {
111 | content: "\e01b";
112 | }
113 | .icon-GitHub-octoface:before {
114 | content: "\e01c";
115 | }
116 | .icon-GitHub-circle:before {
117 | content: "\e01d";
118 | }
119 | .icon-FourSquare:before {
120 | content: "\e01e";
121 | }
122 | .icon-flickr:before {
123 | content: "\e01f";
124 | }
125 | .icon-Flattr:before {
126 | content: "\e020";
127 | }
128 | .icon-facebook:before {
129 | content: "\e021";
130 | }
131 | .icon-Evernote:before {
132 | content: "\e022";
133 | }
134 | .icon-Email:before {
135 | content: "\e023";
136 | }
137 | .icon-DropBox:before {
138 | content: "\e024";
139 | }
140 | .icon-Blogspot:before {
141 | content: "\e025";
142 | }
143 | .icon-BitBucket:before {
144 | content: "\e026";
145 | }
146 | .icon-YouTube-play:before {
147 | content: "\e027";
148 | }
149 |
--------------------------------------------------------------------------------
/assets/img/page/auth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/img/page/auth.png
--------------------------------------------------------------------------------
/assets/img/page/auth_h.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/img/page/auth_h.png
--------------------------------------------------------------------------------
/assets/img/page/blur.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/img/page/blur.jpg
--------------------------------------------------------------------------------
/assets/img/user/heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/img/user/heart.png
--------------------------------------------------------------------------------
/assets/img/user/video-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/assets/img/user/video-play.png
--------------------------------------------------------------------------------
/auth.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Auth Instagram
6 |
7 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var stylus = require('gulp-stylus');
3 | var uglify = require('gulp-uglify');
4 | var csscomb = require('gulp-csscomb');
5 | var cssmin = require('gulp-csso');
6 | var rename = require('gulp-rename');
7 | var webpack = require('gulp-webpack');
8 | var browserSync = require('browser-sync').create();
9 |
10 | var paths = {
11 | scripts: 'src/js/*.js',
12 | jsx: 'src/app/**/*.jsx',
13 | styles: 'src/stylus/**.styl'
14 | };
15 |
16 | gulp.task('uglify', function () {
17 | return gulp.src(paths.scripts)
18 | .pipe(uglify({mangle: true, compress: true}))
19 | .pipe(rename({suffix: '.min'}))
20 | .pipe(gulp.dest('./assets/js'))
21 | .pipe(browserSync.stream());
22 | });
23 |
24 | gulp.task('react', function() {
25 | return gulp.src('src/app/Root.jsx')
26 | .pipe(webpack(require('./webpack.config.js')))
27 | .pipe(gulp.dest('./'));
28 | });
29 |
30 | gulp.task('browser-sync', function() {
31 | browserSync.init({
32 | server: {
33 | baseDir: "./"
34 | }
35 | });
36 | });
37 |
38 | gulp.task('stylus', function () {
39 | return gulp.src('src/stylus/style.styl')
40 | .pipe(stylus())
41 | .pipe(csscomb())
42 | .pipe(gulp.dest('./assets/css'))
43 | .pipe(cssmin())
44 | .pipe(rename({
45 | basename: 'style',
46 | suffix: '.min',
47 | ext: '.css'
48 | }))
49 | .pipe(gulp.dest('./assets/css'))
50 | .pipe(browserSync.stream());
51 | });
52 |
53 | gulp.task('watch', function() {
54 | gulp.watch('./*.html').on('change', browserSync.reload);
55 | gulp.watch(paths.jsx, ['react']);
56 | gulp.watch(paths.scripts, ['uglify']);
57 | gulp.watch(paths.styles, ['stylus']);
58 | });
59 |
60 | gulp.task('default', ['browser-sync', 'react', 'uglify', 'stylus', 'watch']);
61 |
--------------------------------------------------------------------------------
/icon-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/isnifer/react-redux-instagram-example/aa41f2eec42ce05250e7659e60b0b65e8609a473/icon-app.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ReactInstagramApp",
3 | "version": "2.0.0",
4 | "main": "bundle.js",
5 | "author": "Anton Kuznetsov (https://github.com/isnifer)",
6 | "description": "React Redux Instagram App",
7 | "homepage": "http://isnifer.me",
8 | "license": "MIT",
9 | "repository": {
10 | "type": "git",
11 | "url": "git@github.com:isnifer/InstaAngular.git"
12 | },
13 | "scripts": {
14 | "dev": "./node_modules/.bin/gulp"
15 | },
16 | "devDependencies": {
17 | "babel-loader": "^6.2.4",
18 | "browser-sync": "^2.12.3",
19 | "css-loader": "^0.23.1",
20 | "gulp": "^3.9.1",
21 | "gulp-csscomb": "^3.0.7",
22 | "gulp-csso": "^2.0.0",
23 | "gulp-rename": "^1.2.2",
24 | "gulp-stylus": "^2.3.1",
25 | "gulp-uglify": "^1.5.3",
26 | "gulp-webpack": "^1.5.0",
27 | "style-loader": "^0.13.1",
28 | "stylus-loader": "^2.0.0",
29 | "webpack": "^1.12.15"
30 | },
31 | "dependencies": {
32 | "babel-preset-es2015": "^6.6.0",
33 | "babel-preset-react": "^6.5.0",
34 | "babel-preset-stage-0": "^6.5.0",
35 | "history": "^2.0.1",
36 | "react": "^15.0.1",
37 | "react-dom": "^15.0.1",
38 | "react-redux": "^4.4.5",
39 | "react-router": "^2.2.2",
40 | "redux": "^3.4.0",
41 | "redux-logger": "^2.6.1",
42 | "redux-thunk": "^2.0.1"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Instagram App
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/app/Root.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { render } from 'react-dom';
3 | import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router';
4 | import { createHashHistory } from 'history'
5 | import { Provider } from 'react-redux';
6 | import store from './store';
7 |
8 | // Pages
9 | import App from './handlers/App';
10 | import Timeline from './handlers/Timeline';
11 | import SearchPhotos from './handlers/SearchPhotos';
12 | import SearchUsers from './handlers/SearchUsers';
13 | import Profile from './handlers/Profile';
14 | import Followers from './handlers/Followers';
15 | import PageNotFound from './handlers/PageNotFound';
16 |
17 | const appHistory = useRouterHistory(createHashHistory)({queryKey: false});
18 | render((
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ), document.querySelector('.page'));
34 |
--------------------------------------------------------------------------------
/src/app/actions/followers.js:
--------------------------------------------------------------------------------
1 | import { getFollowers } from '../api';
2 | import {
3 | GET_FOLLOWERS_REQUEST,
4 | GET_FOLLOWERS_RESPONSE,
5 | UPDATE_FOLLOWERS_REQUEST,
6 | UPDATE_FOLLOWERS_RESPONSE
7 | } from '../constants';
8 |
9 | const token = localStorage.accessToken;
10 |
11 | export const getFollowersAction = ({url, userId, type}) => (dispatch, getState) => {
12 | dispatch({
13 | type: GET_FOLLOWERS_REQUEST,
14 | payload: {
15 | followers: [],
16 | followersPagination: {}
17 | }
18 | });
19 |
20 | getFollowers({url, userId, type, token}).then(payload => {
21 | dispatch({
22 | type: GET_FOLLOWERS_RESPONSE,
23 | payload
24 | })
25 | });
26 | };
27 |
28 | export const updateFollowersAction = ({url, userId, type}) => (dispatch, getState) => {
29 | dispatch({
30 | type: UPDATE_FOLLOWERS_REQUEST
31 | });
32 |
33 | getFollowers({url, userId, type, token}).then(payload => {
34 | dispatch({
35 | type: UPDATE_FOLLOWERS_RESPONSE,
36 | payload
37 | })
38 | });
39 | };
40 |
--------------------------------------------------------------------------------
/src/app/actions/index.js:
--------------------------------------------------------------------------------
1 | export { getTimelineAction, updateTimelineAction } from './timeline';
2 | export { getProfileDataAction, getProfilePhotosAction, updateProfilePhotosAction } from './profile';
3 | export { searchByUserAction } from './searchByUser';
4 | export { searchByTagAction, getPopularAction } from './searchByTag';
5 | export { getFollowersAction, updateFollowersAction } from './followers';
6 |
--------------------------------------------------------------------------------
/src/app/actions/profile.js:
--------------------------------------------------------------------------------
1 | import { getProfileData, getProfilePhotos } from '../api';
2 | import {
3 | GET_PROFILE_REQUEST,
4 | GET_PROFILE_RESPONSE,
5 | UPDATE_PROFILE_PHOTOS_REQUEST,
6 | UPDATE_PROFILE_PHOTOS_RESPONSE,
7 | GET_PROFILE_PHOTOS_REQUEST,
8 | GET_PROFILE_PHOTOS_RESPONSE
9 | } from '../constants';
10 |
11 | const token = localStorage.accessToken;
12 |
13 | export const getProfileDataAction = ({url, userId}) => (dispatch, getState) => {
14 | dispatch({
15 | type: GET_PROFILE_REQUEST,
16 | payload: {
17 | profileLoaded: false,
18 | profileError: null
19 | }
20 | });
21 |
22 | getProfileData({userId, token}).then(payload => {
23 | payload.profileLoaded = true;
24 |
25 | dispatch({
26 | type: GET_PROFILE_RESPONSE,
27 | payload
28 | });
29 | });
30 | }
31 |
32 | export const getProfilePhotosAction = ({url, userId}) => (dispatch, getState) => {
33 | dispatch({
34 | type: GET_PROFILE_PHOTOS_REQUEST,
35 | profileError: null
36 | });
37 |
38 | getProfilePhotos({url, userId, token}).then(payload => {
39 | dispatch({
40 | type: GET_PROFILE_PHOTOS_RESPONSE,
41 | payload
42 | });
43 | });
44 | }
45 |
46 | export const updateProfilePhotosAction = ({url, userId}) => (dispatch, getState) => {
47 | dispatch({
48 | type: UPDATE_PROFILE_PHOTOS_REQUEST
49 | });
50 |
51 | getProfilePhotos({url, userId, token}).then(payload => {
52 | dispatch({
53 | type: UPDATE_PROFILE_PHOTOS_RESPONSE,
54 | payload
55 | });
56 | });
57 | }
58 |
--------------------------------------------------------------------------------
/src/app/actions/searchByTag.js:
--------------------------------------------------------------------------------
1 | import { searchByTag, getPopular } from '../api';
2 | import {
3 | SEARCH_BY_TAG_REQUEST,
4 | SEARCH_BY_TAG_RESPONSE,
5 | GET_POPULAR_REQUEST,
6 | GET_POPULAR_RESPONSE
7 | } from '../constants';
8 |
9 | const token = localStorage.accessToken;
10 |
11 | export const searchByTagAction = (tag) => (dispatch, getState) => {
12 |
13 | tag = tag.replace(/\s/, '');
14 |
15 | dispatch({
16 | type: SEARCH_BY_TAG_REQUEST
17 | });
18 |
19 | searchByTag({tag, token}).then(payload => {
20 | dispatch({
21 | type: SEARCH_BY_TAG_RESPONSE,
22 | payload
23 | });
24 | });
25 | };
26 |
27 | export const getPopularAction = () => (dispatch, getState) => {
28 |
29 | dispatch({
30 | type: GET_POPULAR_REQUEST
31 | });
32 |
33 | getPopular({token}).then(payload => {
34 | dispatch({
35 | type: GET_POPULAR_RESPONSE,
36 | payload
37 | })
38 | });
39 | };
40 |
--------------------------------------------------------------------------------
/src/app/actions/searchByUser.js:
--------------------------------------------------------------------------------
1 | import { searchByUser } from '../api';
2 | import {
3 | SEARCH_BY_USER_REQUEST,
4 | SEARCH_BY_USER_RESPONSE
5 | } from '../constants';
6 |
7 | const token = localStorage.accessToken;
8 |
9 | export const searchByUserAction = (username) => (dispatch, getState) => {
10 |
11 | username = username.replace(/\s/, '');
12 |
13 | dispatch({
14 | type: SEARCH_BY_USER_REQUEST
15 | });
16 |
17 | searchByUser({username, token}).then(payload => {
18 | dispatch({
19 | type: SEARCH_BY_USER_RESPONSE,
20 | payload
21 | })
22 | });
23 | };
24 |
--------------------------------------------------------------------------------
/src/app/actions/timeline.js:
--------------------------------------------------------------------------------
1 | import { getTimeline } from '../api';
2 | import {
3 | GET_TIMELINE_REQUEST,
4 | GET_TIMELINE_RESPONSE,
5 | UPDATE_TIMELINE_RESPONSE
6 | } from '../constants';
7 |
8 | const token = localStorage.accessToken;
9 | const userId = localStorage.userId;
10 |
11 | export const getTimelineAction = ({url}) => (dispatch, getState) => {
12 |
13 | dispatch({
14 | type: GET_TIMELINE_REQUEST,
15 | payload: {
16 | timelineLoaded: false
17 | }
18 | });
19 |
20 | getTimeline({url, token}).then(payload => {
21 | dispatch({
22 | type: GET_TIMELINE_RESPONSE,
23 | payload: {
24 | timelineItems: payload.data,
25 | pagination: payload.pagination,
26 | timelineLoaded: true
27 | }
28 | })
29 | });
30 | }
31 |
32 | export const updateTimelineAction = ({url}) => (dispatch, getState) => {
33 |
34 | getTimeline({url, token}).then(payload => {
35 | dispatch({
36 | type: UPDATE_TIMELINE_RESPONSE,
37 | payload: {
38 | timelineItems: payload.data,
39 | pagination: payload.pagination
40 | }
41 | })
42 | });
43 | }
44 |
--------------------------------------------------------------------------------
/src/app/api/index.js:
--------------------------------------------------------------------------------
1 | const dataType = 'jsonp';
2 |
3 | export const getFollowers = ({url, userId, type, token}) => {
4 | const defaultUrl = `https://api.instagram.com/v1/users/${userId}/${type}?access_token=${token}`;
5 | return $.ajax({url: url || defaultUrl, dataType}).then(payload => {
6 | return {
7 | followers: payload.data,
8 | followersPagination: payload.pagination
9 | }
10 | });
11 | };
12 |
13 | export const getRelationshipStatus = ({follower, callback, id, token}) => {
14 | const url = `https://api.instagram.com/v1/users/${id}/relationship?access_token=${token}`;
15 | return $.ajax({url, dataType}).then(payload => {
16 | return {
17 | outgoingStatus: data.data.outgoing_status
18 | }
19 | });
20 | }
21 |
22 | export const getProfileData = ({userId, token}) => {
23 | const url = `https://api.instagram.com/v1/users/${userId}?access_token=${token}`;
24 | return $.ajax({url, dataType}).then(payload => {
25 | if (payload.meta.code !== 200) {
26 | return {
27 | profile: {},
28 | counts: {},
29 | profileError: payload.meta.error_message
30 | }
31 | }
32 |
33 | return {
34 | profile: payload.data,
35 | counts: payload.data.counts,
36 | profileError: null
37 | };
38 | });
39 | };
40 |
41 | export const getProfilePhotos = ({url, userId, token}) => {
42 | const defaultUrl = `https://api.instagram.com/v1/users/${userId}/media/recent?access_token=${token}`;
43 |
44 | return $.ajax({url: url || defaultUrl, dataType}).then(payload => {
45 | if (payload.meta.code !== 200) {
46 | return {
47 | profilePhotos: [],
48 | profilePagination: {},
49 | profileError: payload.meta.error_message
50 | }
51 | }
52 |
53 | return {
54 | profilePhotos: payload.data,
55 | profilePagination: payload.pagination,
56 | profileError: null
57 | }
58 | });
59 | };
60 |
61 | export const searchByTag = ({tag, token}) => {
62 | const url = `https://api.instagram.com/v1/tags/${tag}/media/recent?&access_token=${token}`;
63 |
64 | return $.ajax({url: url, dataType}).then(payload => {
65 | if (payload.meta.code !== 200) {
66 | return {
67 | deniedTag: true
68 | }
69 | }
70 |
71 | return {
72 | foundedPhotos: payload.data,
73 | searchPagination: payload.pagination,
74 | deniedTag: false
75 | }
76 | });
77 | }
78 |
79 | export const getPopular = ({token}) => {
80 | const url = `https://api.instagram.com/v1/media/popular/?access_token=${token}`;
81 | return $.ajax({url, dataType}).then(payload => {
82 | return {
83 | foundedPhotos: payload.data
84 | };
85 | });
86 | }
87 |
88 | export const searchByUser = ({username, token}) => {
89 | const url = `https://api.instagram.com/v1/users/search?q=${username}&access_token=${token}`;
90 |
91 | return $.ajax({url: url, dataType}).then(payload => {
92 | return {
93 | foundedUsers: payload.data
94 | }
95 | });
96 | }
97 |
98 | export const getTimeline = ({url, token}) => {
99 | const timelineUrl = `https://api.instagram.com/v1/users/self/feed?access_token=${token}`;
100 | return $.ajax({url: url || timelineUrl, dataType});
101 | }
102 |
--------------------------------------------------------------------------------
/src/app/constants/index.js:
--------------------------------------------------------------------------------
1 | export const GET_FOLLOWERS_REQUEST = 'GET_FOLLOWERS_REQUEST';
2 | export const GET_FOLLOWERS_RESPONSE = 'GET_FOLLOWERS_RESPONSE';
3 | export const UPDATE_FOLLOWERS_REQUEST = 'UPDATE_FOLLOWERS_REQUEST';
4 | export const UPDATE_FOLLOWERS_RESPONSE = 'UPDATE_FOLLOWERS_RESPONSE';
5 |
6 | export const GET_PROFILE_REQUEST = 'GET_PROFILE_REQUEST';
7 | export const GET_PROFILE_RESPONSE = 'GET_PROFILE_RESPONSE';
8 | export const UPDATE_PROFILE_PHOTOS_REQUEST = 'UPDATE_PROFILE_PHOTOS_REQUEST';
9 | export const UPDATE_PROFILE_PHOTOS_RESPONSE = 'UPDATE_PROFILE_PHOTOS_RESPONSE';
10 |
11 | export const GET_PROFILE_PHOTOS_REQUEST = 'GET_PROFILE_PHOTOS_REQUEST';
12 | export const GET_PROFILE_PHOTOS_RESPONSE = 'GET_PROFILE_PHOTOS_RESPONSE';
13 |
14 | export const SEARCH_BY_TAG_REQUEST = 'SEARCH_BY_TAG_REQUEST';
15 | export const SEARCH_BY_TAG_RESPONSE = 'SEARCH_BY_TAG_RESPONSE';
16 |
17 | export const GET_POPULAR_REQUEST = 'GET_POPULAR_REQUEST';
18 | export const GET_POPULAR_RESPONSE = 'GET_POPULAR_RESPONSE';
19 |
20 | export const SEARCH_BY_USER_REQUEST = 'SEARCH_BY_USER_REQUEST';
21 | export const SEARCH_BY_USER_RESPONSE = 'SEARCH_BY_USER_RESPONSE';
22 |
23 | export const GET_TIMELINE_REQUEST = 'GET_TIMELINE_REQUEST';
24 | export const GET_TIMELINE_RESPONSE = 'GET_TIMELINE_RESPONSE';
25 | export const UPDATE_TIMELINE_RESPONSE = 'UPDATE_TIMELINE_RESPONSE';
26 |
--------------------------------------------------------------------------------
/src/app/handlers/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router';
3 |
4 | const userId = localStorage.userId;
5 |
6 | const App = ({routes, children}) => {
7 | const links = routes[0].childRoutes.slice(0, 4).map((link, i) => {
8 | return (
9 |
10 |
13 | {link.name}
14 |
15 |
16 | );
17 | });
18 |
19 | return (
20 |
21 |
26 |
27 | {children}
28 |
29 |
51 |
52 | );
53 | }
54 |
55 | export default App;
56 |
--------------------------------------------------------------------------------
/src/app/handlers/Followers.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { Link } from 'react-router';
3 | import { connect } from 'react-redux';
4 | import { loadOnScrollBottom } from '../../helpers';
5 |
6 | // Actions
7 | import { getFollowersAction, updateFollowersAction } from '../actions';
8 |
9 | class Followers extends Component {
10 | componentDidMount () {
11 | const userId = this.props.params.id;
12 | const type = this.props.route.name;
13 |
14 | this.props.getFollowersAction({userId, type});
15 | }
16 |
17 | render () {
18 | const followers = this.props.model.followers.map((follower, i) => {
19 | return (
20 |
21 |
22 |

23 |
@{follower.username}
24 |
25 |
26 | );
27 | });
28 |
29 | return (
30 |
31 |
32 | {this.props.route.name === 'follows' && 'I Follow' || 'My Followers'}
33 |
34 |
35 | {followers}
36 |
37 |
38 | );
39 | }
40 | }
41 |
42 | Followers.propTypes = {
43 | model: PropTypes.object.isRequired,
44 | };
45 |
46 | export default connect(state => ({
47 | model: {
48 | followers: state.followers,
49 | pagination: state.followersPagination
50 | }
51 | }), {getFollowersAction, updateFollowersAction})(Followers);
52 |
--------------------------------------------------------------------------------
/src/app/handlers/PageNotFound.jsx:
--------------------------------------------------------------------------------
1 | export const PageNotFound = () => {
2 | return (
3 | Page not found
4 | );
5 | }
6 |
--------------------------------------------------------------------------------
/src/app/handlers/Profile.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { Link } from 'react-router';
3 | import { connect } from 'react-redux';
4 | import { loadOnScrollBottom } from '../../helpers';
5 |
6 | // Actions
7 | import { getProfileDataAction, getProfilePhotosAction, updateProfilePhotosAction } from '../actions';
8 |
9 | class Profile extends Component {
10 |
11 | static propTypes = {
12 | model: PropTypes.object.isRequired,
13 | dispatch: PropTypes.func.isRequired
14 | }
15 |
16 | componentDidMount () {
17 | const { dispatch } = this.props;
18 | const userId = this.props.params.id;
19 |
20 | dispatch(getProfileDataAction({userId}));
21 | dispatch(getProfilePhotosAction({userId}));
22 |
23 | loadOnScrollBottom({
24 | dispatch,
25 | action: updateProfilePhotosAction,
26 | that: this,
27 | userId
28 | });
29 | }
30 |
31 | componentWillUnmount () {
32 | console.log('PROFILE UNDMOUNTED');
33 | $(window).off('scroll');
34 | }
35 |
36 | render () {
37 |
38 | const { profile, counts, photos, pagination, error } = this.props.model;
39 |
40 | if (error) {
41 | return (
42 |
43 | {error}
44 |
45 | );
46 | }
47 |
48 | const photoList = photos.map((photo, i) => {
49 | return (
50 |
51 |
52 |
55 |
56 |
Likes: {photo.likes.count}
57 |
58 | );
59 | });
60 |
61 | return (
62 |
63 |
64 |
65 |

69 |
70 |
71 | {profile.username}
72 |
73 |
74 | -
75 | Photos
76 | {counts.media}
77 |
78 | -
79 |
80 | Followers
81 | {counts.followed_by}
82 |
83 |
84 | -
85 |
86 | Follow
87 | {counts.follows}
88 |
89 |
90 |
91 |
100 |
101 |
102 | {photoList}
103 |
104 |
105 | );
106 | }
107 | }
108 |
109 | export default connect(state => ({
110 | model: {
111 | profile: state.profile,
112 | counts: state.counts,
113 | photos: state.profilePhotos,
114 | pagination: state.profilePagination,
115 | error: state.profileError
116 | }
117 | }))(Profile);
118 |
--------------------------------------------------------------------------------
/src/app/handlers/SearchPhotos.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { connect } from 'react-redux';
3 |
4 | // Actions
5 | import { searchByTagAction, getPopularAction } from '../actions';
6 |
7 | class SearchPhotos extends Component {
8 |
9 | static propTypes = {
10 | model: PropTypes.object.isRequired,
11 | dispatch: PropTypes.func.isRequired
12 | }
13 |
14 | search (event) {
15 | event.preventDefault();
16 |
17 | const { dispatch } = this.props;
18 | dispatch(searchByTagAction(this.refs.searchInput.value));
19 | }
20 |
21 | deniedTag () {
22 | this.refs.searchInput.style.border = '2px solid #f00';
23 | setTimeout(() => {
24 | this.refs.searchInput.style.border = 'none';
25 | }, 2000);
26 | }
27 |
28 | componentDidMount () {
29 | this.props.dispatch(getPopularAction());
30 | }
31 |
32 | render () {
33 |
34 | const { foundedPhotos, deniedTag } = this.props.model;
35 |
36 | let searchResultItems = foundedPhotos.map((photo, i) => {
37 | return (
38 |
43 |
44 |
45 | )
46 | });
47 |
48 | if (deniedTag) {
49 | this.deniedTag();
50 |
51 | searchResultItems = (
52 |
53 | Don't try to search {this.refs.searchInput.value} anymore.
54 | This tag is disabled by instagram.
55 |
56 | );
57 | }
58 |
59 | return (
60 |
61 |
69 |
70 | {searchResultItems}
71 |
72 |
73 | );
74 | }
75 | }
76 |
77 | export default connect(state => ({
78 | model: {
79 | foundedPhotos: state.foundedPhotos,
80 | pagination: state.searchPagination,
81 | deniedTag: state.deniedTag
82 | }
83 | }))(SearchPhotos);
84 |
85 |
--------------------------------------------------------------------------------
/src/app/handlers/SearchUsers.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { Link } from 'react-router';
3 | import { connect } from 'react-redux';
4 |
5 | // Actions
6 | import { searchByUserAction } from '../actions';
7 |
8 | class SearchUsers extends Component {
9 |
10 | static propTypes = {
11 | model: PropTypes.object.isRequired,
12 | dispatch: PropTypes.func.isRequired
13 | }
14 |
15 | search (event) {
16 | event.preventDefault();
17 |
18 | const { dispatch } = this.props;
19 | dispatch(searchByUserAction(this.refs.searchInput.value));
20 | }
21 |
22 | render () {
23 | const searchResultItems = this.props.model.users.map((photo, i) => {
24 | return (
25 |
30 |
31 |
32 | )
33 | });
34 |
35 | return (
36 |
37 |
45 |
46 | {searchResultItems}
47 |
48 |
49 | );
50 | }
51 | }
52 |
53 | export default connect(state => ({
54 | model: {
55 | users: state.foundedUsers
56 | }
57 | }))(SearchUsers);
58 |
--------------------------------------------------------------------------------
/src/app/handlers/Timeline.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import { connect } from 'react-redux';
3 | import { loadOnScrollBottom } from '../../helpers';
4 |
5 | // Actions
6 | import { getTimelineAction, updateTimelineAction } from '../actions';
7 |
8 | const token = localStorage.accessToken;
9 | const userId = localStorage.userId;
10 |
11 | const CommentsItem = ({src, author, text}) => {
12 | return (
13 |
14 |
15 | {author}:
16 | {text}
17 |
18 | );
19 | }
20 |
21 | const TimelineUser = ({userId, avatar, username, likes, liked}) => {
22 | return (
23 |
30 | );
31 | }
32 |
33 | const LikeHeart = ({liked, likes}) => {
34 | return (
35 |
36 |
37 | {likes}
38 |
39 | );
40 | }
41 |
42 | const TimelinePhoto = ({id, src}) => {
43 | return (
44 |
48 | );
49 | }
50 |
51 | const TimelineVideo = ({id, src}) => {
52 | return (
53 |
56 | );
57 | }
58 |
59 | const TimelineItem = ({element, id, type, user}) => {
60 | const timelineElement = type === 'video' ?
61 | () :
64 | ();
67 |
68 | const comments = element.comments.data.map((comment, i) => {
69 | return (
70 |
76 | );
77 | });
78 |
79 | return (
80 |
81 |
88 |
89 | {timelineElement}
90 |
93 |
94 |
95 | );
96 | }
97 |
98 | class Timeline extends Component {
99 |
100 | static propTypes = {
101 | model: PropTypes.object.isRequired,
102 | dispatch: PropTypes.func.isRequired
103 | }
104 |
105 | componentDidMount () {
106 | const { dispatch } = this.props;
107 |
108 | // Init
109 | dispatch(getTimelineAction({}));
110 |
111 | loadOnScrollBottom({
112 | dispatch,
113 | action: updateTimelineAction,
114 | that: this
115 | });
116 | }
117 |
118 | componentWillUnmount () {
119 | $(window).off('scroll');
120 | }
121 |
122 | render () {
123 | const items = this.props.model.timelineItems.map((picture, i) => {
124 | return (
125 |
131 | );
132 | });
133 |
134 | return (
135 |
140 | );
141 | }
142 | }
143 |
144 | export default connect(state => ({
145 | model: {
146 | timelineItems: state.timelineItems,
147 | pagination: state.timelinePagination,
148 | timelineLoaded: state.timelineLoaded
149 | }
150 | }))(Timeline);
151 |
--------------------------------------------------------------------------------
/src/app/reducers/followers.js:
--------------------------------------------------------------------------------
1 | import {
2 | GET_FOLLOWERS_REQUEST,
3 | GET_FOLLOWERS_RESPONSE,
4 | UPDATE_FOLLOWERS_RESPONSE
5 | } from '../constants';
6 |
7 | export const followers = (state = [], action) => {
8 | switch (action.type) {
9 | case GET_FOLLOWERS_REQUEST:
10 | case GET_FOLLOWERS_RESPONSE:
11 | return action.payload.followers;
12 | case UPDATE_FOLLOWERS_RESPONSE:
13 | return action.payload.followers.concat(action.payload.followers);
14 | default:
15 | return state;
16 | }
17 | };
18 |
19 |
20 | export const followersPagination = (state = {}, action) => {
21 | switch (action.type) {
22 | case GET_FOLLOWERS_REQUEST:
23 | case GET_FOLLOWERS_RESPONSE:
24 | case UPDATE_FOLLOWERS_RESPONSE:
25 | return action.payload.followersPagination;
26 | default:
27 | return state;
28 | }
29 | };
30 |
--------------------------------------------------------------------------------
/src/app/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 | import { timelineItems, timelinePagination, timelineLoaded } from './timeline';
3 | import {
4 | profile,
5 | counts,
6 | profileLoaded,
7 | profilePhotos,
8 | profilePagination,
9 | profileError
10 | } from './profile';
11 | import { foundedUsers } from './searchByUser';
12 | import {
13 | foundedPhotos,
14 | searchPagination,
15 | deniedTag,
16 | popularPhotos,
17 | popularPagination
18 | } from './searchByTag';
19 | import { followers, followersPagination } from './followers';
20 |
21 | const rootReducer = combineReducers({
22 |
23 | // Timeline
24 | timelineItems,
25 | timelinePagination,
26 | timelineLoaded,
27 |
28 | // Profile
29 | profile,
30 | counts,
31 | profileLoaded,
32 | profilePhotos,
33 | profilePagination,
34 | profileError,
35 |
36 | // Search by user
37 | foundedUsers,
38 |
39 | // Search by tag,
40 | foundedPhotos,
41 | searchPagination,
42 | deniedTag,
43 |
44 | // Popular
45 | popularPhotos,
46 |
47 | // Followers
48 | followers,
49 | followersPagination
50 | });
51 |
52 | export default rootReducer;
53 |
--------------------------------------------------------------------------------
/src/app/reducers/profile.js:
--------------------------------------------------------------------------------
1 | import {
2 | GET_PROFILE_REQUEST,
3 | GET_PROFILE_RESPONSE,
4 | UPDATE_PROFILE_PHOTOS_RESPONSE,
5 | GET_PROFILE_PHOTOS_REQUEST,
6 | GET_PROFILE_PHOTOS_RESPONSE
7 | } from '../constants';
8 |
9 | const initialState = {
10 | profile: {},
11 | counts: {},
12 | profileLoaded: false,
13 | profilePhotos: [],
14 | profilePagination: {},
15 | profileError: null
16 | };
17 |
18 | export const profile = (state = initialState.profile, action) => {
19 | switch (action.type) {
20 | case GET_PROFILE_RESPONSE:
21 | return action.payload.profile || {};
22 | case GET_PROFILE_REQUEST:
23 | default:
24 | return state;
25 | }
26 | };
27 |
28 | export const counts = (state = initialState.counts, action) => {
29 | switch (action.type) {
30 | case GET_PROFILE_RESPONSE:
31 | return action.payload.counts;
32 | case GET_PROFILE_REQUEST:
33 | default:
34 | return state;
35 | }
36 | };
37 |
38 | export const profileLoaded = (state = initialState.profileLoaded, action) => {
39 | switch (action.type) {
40 | case GET_PROFILE_RESPONSE:
41 | case GET_PROFILE_REQUEST:
42 | return action.payload.profileLoaded;
43 | default:
44 | return state;
45 | }
46 | };
47 |
48 | export const profilePhotos = (state = initialState.profilePhotos, action) => {
49 | switch (action.type) {
50 | case UPDATE_PROFILE_PHOTOS_RESPONSE:
51 | return state.concat(action.payload.profilePhotos);
52 | case GET_PROFILE_PHOTOS_RESPONSE:
53 | return action.payload.profilePhotos;
54 | case GET_PROFILE_PHOTOS_REQUEST:
55 | return initialState.profilePhotos;
56 | default:
57 | return state;
58 | }
59 | };
60 |
61 | export const profilePagination = (state = initialState.profilePagination, action) => {
62 | switch (action.type) {
63 | case GET_PROFILE_PHOTOS_RESPONSE:
64 | case UPDATE_PROFILE_PHOTOS_RESPONSE:
65 | return action.payload.profilePagination;
66 | case GET_PROFILE_PHOTOS_REQUEST:
67 | default:
68 | return state;
69 | }
70 | };
71 |
72 |
73 | export const profileError = (state = initialState.profileError, action) => {
74 | switch (action.type) {
75 | case GET_PROFILE_PHOTOS_RESPONSE:
76 | case UPDATE_PROFILE_PHOTOS_RESPONSE:
77 | return action.payload.profileError;
78 | case GET_PROFILE_PHOTOS_REQUEST:
79 | default:
80 | return state;
81 | }
82 | };
83 |
--------------------------------------------------------------------------------
/src/app/reducers/searchByTag.js:
--------------------------------------------------------------------------------
1 | import {
2 | SEARCH_BY_TAG_REQUEST,
3 | SEARCH_BY_TAG_RESPONSE,
4 | GET_POPULAR_REQUEST,
5 | GET_POPULAR_RESPONSE
6 | } from '../constants';
7 |
8 | const initialState = {
9 | foundedPhotos: [],
10 | searchPagination: {},
11 | deniedTag: false
12 | };
13 |
14 | export const foundedPhotos = (state = initialState.foundedPhotos, action) => {
15 | switch (action.type) {
16 | case SEARCH_BY_TAG_RESPONSE:
17 | case GET_POPULAR_RESPONSE:
18 |
19 | // If we try to find denied tag like: xxx, booty, etc
20 | // we will not get anything here
21 | // and we will simply return empty array
22 | return action.payload.foundedPhotos || [];
23 | case GET_POPULAR_REQUEST:
24 | case SEARCH_BY_TAG_REQUEST:
25 | default:
26 | return state;
27 | }
28 | };
29 |
30 |
31 | export const searchPagination = (state = initialState.searchPagination, action) => {
32 | switch (action.type) {
33 | case SEARCH_BY_TAG_RESPONSE:
34 |
35 | // If we try to find denied tag like: xxx, booty, etc
36 | // we will not get anything here
37 | // and we will simply return empty array
38 | return action.payload.searchPagination || [];
39 | case SEARCH_BY_TAG_REQUEST:
40 | default:
41 | return state;
42 | }
43 | };
44 |
45 |
46 | export const deniedTag = (state = initialState.deniedTag, action) => {
47 | switch (action.type) {
48 | case SEARCH_BY_TAG_RESPONSE:
49 | return action.payload.deniedTag;
50 | case SEARCH_BY_TAG_REQUEST:
51 | default:
52 | return state;
53 | }
54 | };
55 |
--------------------------------------------------------------------------------
/src/app/reducers/searchByUser.js:
--------------------------------------------------------------------------------
1 | import {
2 | SEARCH_BY_USER_REQUEST,
3 | SEARCH_BY_USER_RESPONSE
4 | } from '../constants';
5 |
6 | export const foundedUsers = (state = [], action) => {
7 | switch (action.type) {
8 | case SEARCH_BY_USER_RESPONSE:
9 | return action.payload.foundedUsers;
10 | case SEARCH_BY_USER_REQUEST:
11 | default:
12 | return state;
13 | }
14 | };
15 |
--------------------------------------------------------------------------------
/src/app/reducers/timeline.js:
--------------------------------------------------------------------------------
1 | import {
2 | GET_TIMELINE_REQUEST,
3 | GET_TIMELINE_RESPONSE,
4 | UPDATE_TIMELINE_RESPONSE
5 | } from '../constants';
6 |
7 | const initialState = {
8 | timelineItems: [],
9 | timelinePagination: {},
10 | timelineLoaded: false
11 | };
12 |
13 | export const timelineItems = (state = initialState.timelineItems, action) => {
14 | switch (action.type) {
15 | case GET_TIMELINE_REQUEST:
16 | return state;
17 | case GET_TIMELINE_RESPONSE:
18 | case UPDATE_TIMELINE_RESPONSE:
19 | return state.concat(action.payload.timelineItems);
20 | default:
21 | return state;
22 | }
23 | };
24 |
25 | export const timelinePagination = (state = initialState.timelinePagination, action) => {
26 | switch (action.type) {
27 | case GET_TIMELINE_REQUEST:
28 | return state;
29 | case GET_TIMELINE_RESPONSE:
30 | case UPDATE_TIMELINE_RESPONSE:
31 | return action.payload.pagination;
32 | default:
33 | return state;
34 | }
35 | };
36 |
37 | export const timelineLoaded = (state = initialState.timelineLoaded, action) => {
38 | switch (action.type) {
39 | case GET_TIMELINE_REQUEST:
40 | case GET_TIMELINE_RESPONSE:
41 | return action.payload.timelineLoaded;
42 | default:
43 | return state;
44 | }
45 | };
46 |
--------------------------------------------------------------------------------
/src/app/store/index.js:
--------------------------------------------------------------------------------
1 | import reducer from '../reducers';
2 | import { createStore, applyMiddleware } from 'redux';
3 | import logger from 'redux-logger';
4 | import thunk from 'redux-thunk';
5 |
6 | const middleware = process.env.NODE_ENV === 'production' ? [thunk] : [thunk, logger()];
7 | const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);
8 | const store = createStoreWithMiddleware(reducer);
9 |
10 | export default store;
11 |
--------------------------------------------------------------------------------
/src/helpers/index.js:
--------------------------------------------------------------------------------
1 | export const loadOnScrollBottom = ({dispatch, action, userId, that}) => {
2 | $(window).off('scroll');
3 | $(window).on('scroll', function() {
4 | if($(this).scrollTop() + $(this).height() == $(document).height()) {
5 | dispatch(action({url: that.props.model.pagination.next_url, userId}));
6 | }
7 | });
8 | };
9 |
--------------------------------------------------------------------------------
/src/stylus/_about.styl:
--------------------------------------------------------------------------------
1 | .about
2 | text-align center
3 | padding-top 40px
4 |
5 | &__header
6 | color #fff
7 | text-shadow 0 1px 1px #333
8 | font bold 2em "Roboto Condensed", Arial, Tahoma
9 |
10 | &__text
11 | color #333
12 | text-shadow 0 1px 1px #fff
13 |
14 | a
15 | text-decoration none
16 | color #333
17 | border-bottom 1px dashed #27ae60
18 | -webkit-transition border-color 0.5s ease
19 | -moz-transition border-color 0.5s ease
20 | transition border-color 0.5s ease
21 |
22 | &:hover
23 | border-color #ff4c4b
24 |
--------------------------------------------------------------------------------
/src/stylus/_column.styl:
--------------------------------------------------------------------------------
1 | [class*="column_xs-"]
2 | float left
3 |
4 | .column
5 | position relative
6 | min-height 1px
7 | padding-left 10px
8 | padding-right 10px
9 |
10 | setColumn(xs, 12)
11 | createOffset(xs, 12)
--------------------------------------------------------------------------------
/src/stylus/_comments.styl:
--------------------------------------------------------------------------------
1 | .comments
2 | margin 10px 0 0 100px
3 | padding 0
4 | list-style none
5 | overflow hidden
6 |
7 | &__item
8 | display block
9 | margin 0 0 5px 0
10 |
11 | &__pic
12 | width 20px
13 | margin-right 5px
14 | float left
15 |
16 | &__username
17 | font-size 0.85em
18 | font-weight bold
19 | color #444444
20 | text-decoration none
21 |
22 | &:hover
23 | border-bottom 1px dashed #444
24 |
25 | &__text
26 | font-size 0.85em
--------------------------------------------------------------------------------
/src/stylus/_feed.styl:
--------------------------------------------------------------------------------
1 | .feed
2 | margin 2% auto 0
3 | padding 0
4 | width 95%
5 | list-style none
6 |
7 | &__item
8 | display block
9 | width 76%
10 | min-height 400px
11 | margin 40px auto 0
--------------------------------------------------------------------------------
/src/stylus/_follow.styl:
--------------------------------------------------------------------------------
1 | .follow
2 |
3 | &__header
4 | color #fff
5 | text-shadow 0 1px 1px #333
6 | font-weight 700
7 | font-size 2em
8 | margin 20px 0
9 | text-align center
10 |
11 | &__list
12 | margin 0
13 | padding 0
14 | list-style none
15 |
16 | &__item
17 | float left
18 | width 100%
19 | height 100px
20 | vertical-align top
21 | margin 0
22 | background #fff
23 | border-bottom 1px solid #17b287
24 | border-right 1px solid #17b287
25 | border-left 1px solid #17b287
26 |
27 | &:first-child
28 | border-top 1px solid #17b287
29 |
30 | &:nth-child(4n)
31 | margin-right 0
32 |
33 | a
34 | text-decoration none
35 | color #333
36 | font-weight bold
37 | font-size 1.25em
38 | text-align center
39 |
40 | &__avatar
41 | display inline-block
42 | width 99px
43 | float left
44 | margin-right 10px
45 |
46 | &__username
47 | -webkit-transition color 0.5s ease
48 | -moz-transition color 0.5s ease
49 | transition color 0.5s ease
50 | overflow hidden
51 | position relative
52 | top 35px
53 |
54 | &:hover
55 | color #ff4c4b
56 |
57 | &__btn
58 | border 0
59 | padding 3px 10px
60 | box-shadow 2px 2px 2px 1px rgba(0,0,0,.5)
61 | background #ff4c4b
62 | color #fff
63 | float right
64 | margin 35px 10px 0 0
65 |
66 | &_read
67 | background #27ae60
68 |
--------------------------------------------------------------------------------
/src/stylus/_fonts.styl:
--------------------------------------------------------------------------------
1 | /* Подключаемые шрифты */
2 | @import url("http://fonts.googleapis.com/css?family=PT+Sans:400,700&subset=latin,cyrillic")
3 | @import url("../fonts/grand.css")
--------------------------------------------------------------------------------
/src/stylus/_footer.styl:
--------------------------------------------------------------------------------
1 | .footer
2 | position absolute
3 | bottom 0
4 | width 100%
5 | height 89px
6 | background #444444
7 | border-top 1px solid #4f4f50
8 | border-bottom 1px solid #4f4f50
9 |
10 | &__copyright
11 | float right
12 | color #dddbdb
13 | font normal 0.75em "Tahoma", Arial, Verdana
14 | margin 38px 60px 0 0
--------------------------------------------------------------------------------
/src/stylus/_form.styl:
--------------------------------------------------------------------------------
1 | .form
2 | position relative
3 | width 605px
4 |
5 | &__field
6 | margin 0
7 | padding 0
8 | border 0
9 |
10 | &__label
11 | display block
12 | padding 5px 0
13 |
14 | &__label-title
15 | display inline-block
16 | width 200px
17 | vertical-align top
18 |
19 | &__input, &__select, &__textarea
20 | width 400px
21 | font-size (14/16)*1em
22 | outline none
23 | border 1px solid #a0a0a0
24 |
25 | &__input
26 | height 30px
27 |
28 | &__input, &__textarea
29 | padding 0 5px
30 |
31 | &:focus
32 | box-shadow 0 0 2px 2px rgb(255, 229, 0)
33 |
34 | &__select
35 | width 200px
36 |
37 | &__textarea
38 | padding 3px 5px
39 | resize vertical
40 |
41 | &__answer
42 | display inline-block
43 | width 400px
44 |
45 | &__radio-wrapper
46 | display block
--------------------------------------------------------------------------------
/src/stylus/_globals.styl:
--------------------------------------------------------------------------------
1 | *
2 | -webkit-box-sizing border-box
3 | -moz-box-sizing border-box
4 | box-sizing border-box
5 |
6 | .g-clf:after, .g-clf:before
7 | clear both
8 | content ""
9 | display table
--------------------------------------------------------------------------------
/src/stylus/_grid.styl:
--------------------------------------------------------------------------------
1 | .grid
2 | display block
--------------------------------------------------------------------------------
/src/stylus/_header.styl:
--------------------------------------------------------------------------------
1 | /* Шапка */
2 | .header
3 | width 100%
4 | height 50px
5 | background #17b287
6 | position fixed
7 | top 0
8 | left 0
9 | z-index 9999
10 | box-shadow 0 1px 1px 2px rgba(0,0,0,.5)
--------------------------------------------------------------------------------
/src/stylus/_loader.styl:
--------------------------------------------------------------------------------
1 | @-moz-keyframes heartbeat-loader {
2 | 0% {
3 | -moz-transform: rotate(45deg) scale(1);
4 | transform: rotate(45deg) scale(1);
5 | }
6 | 14% {
7 | -moz-transform: rotate(45deg) scale(1.3);
8 | transform: rotate(45deg) scale(1.3);
9 | }
10 | 28% {
11 | -moz-transform: rotate(45deg) scale(1);
12 | transform: rotate(45deg) scale(1);
13 | }
14 | 42% {
15 | -moz-transform: rotate(45deg) scale(1.3);
16 | transform: rotate(45deg) scale(1.3);
17 | }
18 | 70% {
19 | -moz-transform: rotate(45deg) scale(1);
20 | transform: rotate(45deg) scale(1);
21 | }
22 | }
23 | @-webkit-keyframes heartbeat-loader {
24 | 0% {
25 | -webkit-transform: rotate(45deg) scale(1);
26 | transform: rotate(45deg) scale(1);
27 | }
28 | 14% {
29 | -webkit-transform: rotate(45deg) scale(1.3);
30 | transform: rotate(45deg) scale(1.3);
31 | }
32 | 28% {
33 | -webkit-transform: rotate(45deg) scale(1);
34 | transform: rotate(45deg) scale(1);
35 | }
36 | 42% {
37 | -webkit-transform: rotate(45deg) scale(1.3);
38 | transform: rotate(45deg) scale(1.3);
39 | }
40 | 70% {
41 | -webkit-transform: rotate(45deg) scale(1);
42 | transform: rotate(45deg) scale(1);
43 | }
44 | }
45 | @keyframes heartbeat-loader {
46 | 0% {
47 | -moz-transform: rotate(45deg) scale(1);
48 | -ms-transform: rotate(45deg) scale(1);
49 | -webkit-transform: rotate(45deg) scale(1);
50 | transform: rotate(45deg) scale(1);
51 | }
52 | 14% {
53 | -moz-transform: rotate(45deg) scale(1.3);
54 | -ms-transform: rotate(45deg) scale(1.3);
55 | -webkit-transform: rotate(45deg) scale(1.3);
56 | transform: rotate(45deg) scale(1.3);
57 | }
58 | 28% {
59 | -moz-transform: rotate(45deg) scale(1);
60 | -ms-transform: rotate(45deg) scale(1);
61 | -webkit-transform: rotate(45deg) scale(1);
62 | transform: rotate(45deg) scale(1);
63 | }
64 | 42% {
65 | -moz-transform: rotate(45deg) scale(1.3);
66 | -ms-transform: rotate(45deg) scale(1.3);
67 | -webkit-transform: rotate(45deg) scale(1.3);
68 | transform: rotate(45deg) scale(1.3);
69 | }
70 | 70% {
71 | -moz-transform: rotate(45deg) scale(1);
72 | -ms-transform: rotate(45deg) scale(1);
73 | -webkit-transform: rotate(45deg) scale(1);
74 | transform: rotate(45deg) scale(1);
75 | }
76 | }
77 | /* :not(:required) hides this rule from IE9 and below */
78 | .heartbeat-loader:not(:required) {
79 | -moz-animation: heartbeat-loader 1300ms ease 0s infinite normal;
80 | -webkit-animation: heartbeat-loader 1300ms ease 0s infinite normal;
81 | animation: heartbeat-loader 1300ms ease 0s infinite normal;
82 | display: inline-block;
83 | position: relative;
84 | overflow: hidden;
85 | text-indent: -9999px;
86 | width: 36px;
87 | height: 36px;
88 | -moz-transform: rotate(45deg) scale(1);
89 | -ms-transform: rotate(45deg) scale(1);
90 | -webkit-transform: rotate(45deg) scale(1);
91 | transform: rotate(45deg) scale(1);
92 | -moz-transform-origin: 50% 50%;
93 | -ms-transform-origin: 50% 50%;
94 | -webkit-transform-origin: 50% 50%;
95 | transform-origin: 50% 50%;
96 | }
97 | .heartbeat-loader:not(:required):after, .heartbeat-loader:not(:required):before {
98 | position: absolute;
99 | content: "";
100 | background: #e87;
101 | }
102 | .heartbeat-loader:not(:required):before {
103 | -moz-border-radius-topleft: 12px;
104 | -webkit-border-top-left-radius: 12px;
105 | border-top-left-radius: 12px;
106 | -moz-border-radius-bottomleft: 12px;
107 | -webkit-border-bottom-left-radius: 12px;
108 | border-bottom-left-radius: 12px;
109 | top: 12px;
110 | left: 0;
111 | width: 36px;
112 | height: 24px;
113 | }
114 | .heartbeat-loader:not(:required):after {
115 | -moz-border-radius-topleft: 12px;
116 | -webkit-border-top-left-radius: 12px;
117 | border-top-left-radius: 12px;
118 | -moz-border-radius-topright: 12px;
119 | -webkit-border-top-right-radius: 12px;
120 | border-top-right-radius: 12px;
121 | top: 0;
122 | left: 12px;
123 | width: 24px;
124 | height: 12px;
125 | }
126 |
--------------------------------------------------------------------------------
/src/stylus/_main.styl:
--------------------------------------------------------------------------------
1 | .main
2 | margin 0 auto
3 | padding 50px 10px 115px
--------------------------------------------------------------------------------
/src/stylus/_menu.styl:
--------------------------------------------------------------------------------
1 | .menu
2 | margin 0
3 | padding 14px 0 0
4 | list-style none
5 | text-align center
6 |
7 | &__item
8 | display inline-block
9 | margin-right 15px
10 | cursor pointer
11 |
12 | &:last-child
13 | margin-right 0
14 |
15 | &__link
16 | text-decoration none
17 | color #17b287
18 | background #f9f9f9
19 | padding 5px 20px
20 | -webkit-transition color 0.5s ease
21 | -moz-transition color 0.5s ease
22 | transition color 0.5s ease
23 |
24 | &:hover
25 | color #ff4c4b
--------------------------------------------------------------------------------
/src/stylus/_mixins.styl:
--------------------------------------------------------------------------------
1 | box-shadow(arguments...)
2 | -webkit-box-shadow arguments
3 | -moz-box-shadow arguments
4 | box-shadow arguments
5 |
6 | gradient(arguments...)
7 | background -moz-linear-gradient(top, arguments)
8 | background -webkit-linear-gradient(top, arguments)
9 | background linear-gradient(to bottom, arguments)
10 |
11 | grid(ratio)
12 | width (100/12) * unit(ratio, '%')
13 |
14 | offset(ratio)
15 | margin-left (100/12) * unit(ratio, '%')
16 |
17 | setColumn(name, columns)
18 |
19 | for num in (1..columns)
20 | &_{name}-{num}
21 | grid num
22 |
23 | createOffset(name, columns)
24 |
25 | for num in (1..columns)
26 | &__offset_{name}-{num}
27 | offset num
--------------------------------------------------------------------------------
/src/stylus/_normalize.styl:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.0 | MIT License | git.io/normalize */
2 |
3 | html
4 | font-family sans-serif
5 | -ms-text-size-adjust 100%
6 | -webkit-text-size-adjust 100%
7 |
8 | body
9 | margin 0
10 |
11 | article,
12 | aside,
13 | details,
14 | figcaption,
15 | figure,
16 | footer,
17 | header,
18 | hgroup,
19 | main,
20 | nav,
21 | section,
22 | summary
23 | display block
24 |
25 | audio,
26 | canvas,
27 | progress,
28 | video
29 | display inline-block
30 | vertical-align baseline
31 |
32 |
33 | audio:not([controls])
34 | display none
35 | height 0
36 |
37 | [hidden],
38 | template
39 | display none
40 |
41 | a
42 | background transparent
43 |
44 |
45 | a:active,
46 | a:hover
47 | outline 0
48 |
49 | abbr[title]
50 | border-bottom 1px dotted
51 |
52 | b,
53 | strong
54 | font-weight bold
55 |
56 | dfn
57 | font-style italic
58 |
59 | h1
60 | font-size 2em
61 | margin 0.67em 0
62 |
63 | mark
64 | background #ff0
65 | color #000
66 |
67 | small
68 | font-size 80%
69 |
70 | sub,
71 | sup
72 | font-size 75%
73 | line-height 0
74 | position relative
75 | vertical-align baseline
76 |
77 |
78 | sup
79 | top -0.5em
80 |
81 |
82 | sub
83 | bottom -0.25em
84 |
85 | img
86 | border 0
87 |
88 | svg:not(:root)
89 | overflow hidden
90 |
91 | figure
92 | margin 1em 40px
93 |
94 | hr
95 | -moz-box-sizing content-box
96 | box-sizing content-box
97 | height 0
98 |
99 | pre
100 | overflow auto
101 |
102 | code,
103 | kbd,
104 | pre,
105 | samp
106 | font-family monospace, monospace
107 | font-size 1em
108 |
109 | button,
110 | input,
111 | optgroup,
112 | select,
113 | textarea
114 | color inherit
115 | font inherit
116 | margin 0
117 |
118 | button
119 | overflow visible
120 |
121 | button,
122 | select
123 | text-transform none
124 |
125 | button,
126 | html input[type="button"],
127 | input[type="reset"],
128 | input[type="submit"]
129 | -webkit-appearance button
130 | cursor pointer
131 |
132 | button[disabled],
133 | html input[disabled]
134 | cursor default
135 |
136 | button::-moz-focus-inner,
137 | input::-moz-focus-inner
138 | border 0
139 | padding 0
140 |
141 | input
142 | line-height normal
143 |
144 | input[type="checkbox"],
145 | input[type="radio"]
146 | box-sizing border-box
147 | padding 0
148 |
149 |
150 | input[type="number"]::-webkit-inner-spin-button,
151 | input[type="number"]::-webkit-outer-spin-button
152 | height auto
153 |
154 |
155 | input[type="search"]
156 | -webkit-appearance textfield
157 | -moz-box-sizing content-box
158 | -webkit-box-sizing content-box
159 | box-sizing content-box
160 |
161 |
162 | input[type="search"]::-webkit-search-cancel-button,
163 | input[type="search"]::-webkit-search-decoration
164 | -webkit-appearance none
165 |
166 |
167 | fieldset
168 | border 1px solid #c0c0c0
169 | margin 0 2px
170 | padding 0.35em 0.625em 0.75em
171 |
172 |
173 | legend
174 | border 0
175 | padding 0
176 |
177 | textarea
178 | overflow auto
179 |
180 |
181 | optgroup
182 | font-weight bold
183 |
184 | table
185 | border-collapse collapse
186 | border-spacing 0
187 |
188 |
189 | td,
190 | th
191 | padding 0
192 |
--------------------------------------------------------------------------------
/src/stylus/_page.styl:
--------------------------------------------------------------------------------
1 | /* Обвязка */
2 | html, body
3 | height 100%
4 | font normal 16px "PT Sans", Verdana, Tahoma
5 |
6 | body
7 | background #bdc3c7
8 |
9 | &.welcome
10 | background url(../img/page/blur.jpg) no-repeat 0 0
11 | -webkit-background-size cover
12 | -moz-background-size cover
13 | -ms-background-size cover
14 | background-size cover
15 |
16 | .auth
17 | display block
18 | width 200px
19 | height 29px
20 | background url(../img/page/auth.png) no-repeat 0 0
21 | text-indent -9999px
22 | outline none
23 | position absolute
24 | top 50%
25 | left 50%
26 | margin-left -100px
27 | cursor pointer
28 |
29 | &:hover
30 | background url(../img/page/auth_h.png) no-repeat 0 0
31 |
32 | .page
33 | position relative
34 | min-height 100%
35 | margin 0 auto
--------------------------------------------------------------------------------
/src/stylus/_photo-list.styl:
--------------------------------------------------------------------------------
1 | .photo-list
2 | margin 0
3 | padding 0
4 | list-style none
5 |
6 | &__item
7 | display inline-block
8 | width 20.5%
9 | margin 0 6% 6% 0
10 | cursor pointer
11 |
12 | &:nth-child(4n)
13 | margin-right 0
14 |
15 | img
16 | max-width 100%
17 | box-shadow 0px 0px 2px 3px rgba(0,0,0,.7)
18 |
19 | &__likes
20 | font-size 0.7em
21 | color #333
22 | float right
23 |
24 | &:hover
25 | text-decoration underline
--------------------------------------------------------------------------------
/src/stylus/_photo.styl:
--------------------------------------------------------------------------------
1 | .photo
2 | overflow hidden
3 |
4 | &__pic
5 | display block
6 | width 500px
7 | max-width 100%
8 | margin-left 100px
--------------------------------------------------------------------------------
/src/stylus/_popup.styl:
--------------------------------------------------------------------------------
1 | /* Всплывающие окна */
--------------------------------------------------------------------------------
/src/stylus/_profile.styl:
--------------------------------------------------------------------------------
1 | .profile
2 | margin 40px 0 0
3 |
4 | &__photo
5 | display block
6 | margin 0 auto
7 | width 150px
8 | height 150px
9 |
10 | &__username
11 | color #fff
12 | text-shadow 0 1px 2px #333
13 | text-align center
14 | line-height 20px
15 | margin 10px 0 0
16 | font bold 2em
17 |
18 | &__stats, &__info
19 | margin 20px 0 30px
20 | padding 0
21 | list-style none
22 | text-align center
23 |
24 | &__item
25 | display inline-block
26 | text-align center
27 | padding 0 20px
28 | font normal 1.25em
29 | color #fff
30 | text-shadow 0 1px 1px #333
31 |
32 | a
33 | text-decoration none
34 | color #fff
35 | text-shadow 0 1px 1px #333
36 | -webkit-transition color 0.5s ease
37 | -moz-transition color 0.5s ease
38 | transition color 0.5s ease
39 |
40 | &:hover
41 | color #17b287
42 |
43 | &__info
44 |
45 | .profile__item
46 | color #333
47 | text-shadow none
48 | display block
49 | text-align center
--------------------------------------------------------------------------------
/src/stylus/_responsive.styl:
--------------------------------------------------------------------------------
1 | // Small devices (tablets, 768px and up)
2 | @media (min-width: 768px)
3 |
4 | [class*="column_sm-"]
5 | float left
6 |
7 | .column
8 |
9 | setColumn(sm, 12)
10 |
11 | createOffset(sm, 12)
12 |
13 | // Medium devices (desktops, 992px and up)
14 | @media (min-width: 992px)
15 |
16 | .page
17 | width 940px
18 |
19 | [class*="column_md-"]
20 | float left
21 |
22 | .column
23 |
24 | setColumn(md, 12)
25 |
26 | createOffset(md, 12)
27 |
28 | // Large devices (large desktops, 1200px and up)
29 | @media (min-width: 1170px)
30 |
31 | [class*="column_lg-"]
32 | float left
33 |
34 | .column
35 |
36 | setColumn(lg, 12)
37 |
38 | createOffset(lg, 12)
--------------------------------------------------------------------------------
/src/stylus/_row.styl:
--------------------------------------------------------------------------------
1 | .row
2 | margin-bottom 15px
--------------------------------------------------------------------------------
/src/stylus/_search.styl:
--------------------------------------------------------------------------------
1 | .search
2 | margin 40px 0 0
3 |
4 | &__form
5 | width 100%
6 | height 60px
7 | margin 0 auto 30px
8 |
9 | &__input
10 | display inline-block
11 | width 100%
12 | height 60px
13 | font normal 24px "Roboto Condensed"
14 | color #bdbab4
15 | outline none
16 | padding 0 14px
17 | border 0
--------------------------------------------------------------------------------
/src/stylus/_sidebar.styl:
--------------------------------------------------------------------------------
1 | /* Сайдбар */
--------------------------------------------------------------------------------
/src/stylus/_social.styl:
--------------------------------------------------------------------------------
1 | .social
2 | float left
3 | margin 32px 0 0 60px
4 | padding 0
5 | list-style none
6 |
7 | &__item
8 | display inline-block
9 | float left
10 | margin-left 15px
11 |
12 | &:first-child
13 | margin-left 0
14 |
15 | &__link
16 | color #dddbdb
17 | font normal 24px "Arial", Tahoma, Verdana
18 | text-decoration none
19 | -webkit-transition color 0.4s ease
20 | -moz-transition color 0.4s ease
21 | transition color 0.4s ease
22 | text-indent -9999px
23 |
24 | &:hover
25 | color #27ae60
--------------------------------------------------------------------------------
/src/stylus/_user.styl:
--------------------------------------------------------------------------------
1 | .user
2 | margin-bottom 10px
3 |
4 | &__pic
5 | width 100px
6 | height 100px
7 | float left
8 | margin-right 20px
9 |
10 | img
11 | width 100px
12 | border-radius 50%
13 |
14 | &__name
15 | color #333
16 | display block
17 |
18 | &__likes
19 | height 80px
20 | display block
21 |
22 | &__like
23 | width 80px
24 | height 80px
25 | display inline-block
26 | vertical-align middle
27 | background url("data:image/png;base64,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") no-repeat 0 0
28 | cursor pointer
29 |
30 | &:hover, &_liked
31 | background-position 0 -80px
32 |
33 | &__likes-count
34 | position relative
35 | font-size 2.5em
36 | display inline-block
37 | vertical-align middle
38 |
39 | &__video
40 | cursor pointer
41 | display block
42 | width 100px
43 | height 100px
44 | background url(../img/user/video-play.png)
--------------------------------------------------------------------------------
/src/stylus/_vars.styl:
--------------------------------------------------------------------------------
1 | mobileBreakPoint = 768px
2 | tabletBreakPoint = 992px
3 | wideBreakPoint = 1170px
--------------------------------------------------------------------------------
/src/stylus/style.styl:
--------------------------------------------------------------------------------
1 | @import "_vars"
2 | @import "_mixins"
3 |
4 | /* Шрифты */
5 | @import "_fonts"
6 |
7 | /* Normalize */
8 | @import "_normalize"
9 |
10 | /* Глобальные стили */
11 | @import "_globals"
12 |
13 | /* Обвязка */
14 | @import "_page"
15 |
16 | /* Шапка */
17 | @import "_header"
18 |
19 | /* Menu */
20 | @import "_menu"
21 |
22 | /* Основной контент */
23 | @import "_main"
24 |
25 | /* Боковое меню */
26 | @import "_sidebar"
27 |
28 | /* Подвал */
29 | @import "_footer"
30 |
31 | /* Форма */
32 | @import "_form"
33 |
34 | /* Сетка */
35 | @import "_grid"
36 |
37 | /* Строка сетки */
38 | @import "_row"
39 |
40 | /* Колонка сетки */
41 | @import "_column"
42 |
43 | /* Profile */
44 | @import "_profile"
45 |
46 | /* Popular */
47 | @import "_search"
48 |
49 | /* Photo List */
50 | @import "_photo-list"
51 |
52 | /* About page */
53 | @import "_about"
54 |
55 | /* Social Icons */
56 | @import "_social"
57 |
58 | /* Feed */
59 | @import "_feed"
60 |
61 | /* User in Feed */
62 | @import "_user"
63 |
64 | /* Photo in Feed */
65 | @import "_photo"
66 |
67 | /* Comments in Feed */
68 | @import "_comments"
69 |
70 | /* Followers and Follows */
71 | @import "_follow"
72 |
73 | /* Всплывающие окна */
74 | @import "_popup"
75 |
76 | /* Responsive */
77 | @import "_responsive"
78 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | var path = require('path');
3 |
4 | module.exports = {
5 | entry: './src/app/Root.jsx',
6 | output: {
7 | publicPath: "/",
8 | filename: 'bundle.js'
9 | },
10 | context: __dirname,
11 | module: {
12 | loaders: [
13 | {
14 | test: /\.jsx?$/,
15 | loader: 'babel',
16 | query: {
17 | presets: ['es2015', 'stage-0', 'react']
18 | },
19 | exclude: /node_modules/,
20 | include: path.resolve(__dirname, 'src')
21 | },
22 | {test: /\.styl$/, loaders: ['style', 'css', 'stylus']}
23 | ]
24 | },
25 | resolve: {
26 | extensions: ['', '.js', '.jsx']
27 | }
28 | };
29 |
--------------------------------------------------------------------------------