26 Commits
Author SHA1 Message Date
tmshv 00e9d65789 linear timeline; 2015-03-28 00:04:08 +03:00
tmshv b9d52b5327 + development index; 2015-03-28 00:02:22 +03:00
tmshv 385cecfc97 default router index file moved to config; 2015-03-28 00:01:49 +03:00
tmshv a67b3244ef fix: package.json are broken; 2015-03-28 00:00:50 +03:00
tmshv a2ae10771e v 3.1.0 2015-03-16 17:27:49 +03:00
tmshv dc130ad394 + io; other changes; 2015-03-16 17:21:01 +03:00
tmshv 754c8bf9a4 helmet code style; 2015-03-14 04:28:49 +03:00
tmshv d69bec8c22 - bin/insta 2015-03-14 04:26:07 +03:00
tmshv f687425bdc news bugfix: sorting news when paging 2015-03-14 04:24:18 +03:00
tmshv 1ebfcea16b base instagram supporting; 2015-03-14 04:23:43 +03:00
tmshv 17923e3730 instagram now works as prototype; 2015-03-10 13:41:49 +03:00
tmshv 67ea5ea96c + koa-bodyparser; 2015-03-10 13:34:39 +03:00
tmshv 1069868ef0 timeline more spinner width update; 2015-03-09 00:56:41 +03:00
tmshv df2ec90daa + test 2015-03-09 00:44:05 +03:00
tmshv bed2cfad22 timeline more; spinner; common update; 2015-03-09 00:43:46 +03:00
tmshv 38fac9c033 news pinned feature; 2015-03-08 07:39:29 +03:00
tmshv e7c77e18c6 timeline update; 2015-03-08 06:56:36 +03:00
tmshv 38e0a4dadd instagram update; 2015-03-08 06:56:20 +03:00
tmshv 0372a81304 .gitignore private update; 2015-03-08 06:55:15 +03:00
tmshv 0a3c530599 timeline update; 2015-03-07 18:55:07 +03:00
tmshv 435c8aef7f news sorting by date 2015-03-07 18:54:05 +03:00
tmshv 36febf0e3b news route update; + /news/<name>; mime routers 2015-03-07 09:23:59 +03:00
tmshv 5b477aa41c layout update; mobile version; data update; 2015-03-02 04:44:53 +03:00
tmshv 8d0f88ec81 main title update; 2015-03-01 20:19:18 +03:00
tmshv b7f1599777 new title; new telephone; home page update; 2015-03-01 20:17:31 +03:00
tmshv ec67d8d9d8 package.json update; 2015-03-01 19:18:59 +03:00
49 changed files with 1318 additions and 511 deletions

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@
.idea
*.sublime*
private.json
private*.json
/node_modules
/bower_components
Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

+11 -7
View File
@@ -15,15 +15,9 @@
}
.docblock{
// width:100%;
margin-bottom: 40px;
text-align: center;
// .docs{
// text-align: left;
// }
h2{
margin-left: 50px;
text-align: left;
@@ -61,4 +55,14 @@
padding: 0;
display: block;
}
}
}
@media screen and (max-device-width: 400px){
.doc{
margin: 30px 35px;
img{
max-width: 250px;
}
}
}
+26 -1
View File
@@ -2,6 +2,8 @@ footer{
position: relative;
background-color: black;
color: #ffffff;
overflow-x: scroll;
margin: 0;
&:before{
content: '';
@@ -14,7 +16,7 @@ footer{
.info-block{
display: flex;
margin: 0 20px;
margin: 0;
& > div{
margin: 0 30px 0 10px;
@@ -28,4 +30,27 @@ footer{
ul{
list-style: none;
}
}
.footer-content{
min-width: 500px;
}
@media screen and (max-device-width: 500px){
footer{
font-size: 8pt;
.info-block{
display: block;
margin: 0;
& > div{
margin: 0 30px 0 10px;
}
p{
margin: 0;
}
}
}
}
+26
View File
@@ -8,3 +8,29 @@
animation: scaleUp 0.3s both ease-in;
}
}
.main-block {
width: 100%;
margin-top: 5px;
.telephone {
font-size: 1.25em;
margin-left: 30px;
}
h1 {
font-size: 18pt;
text-align: center;
font-weight: normal;
margin: 0;
padding: 0;
}
}
@media screen and (max-device-width: 500px) {
.main-block {
.telephone {
display: none;
}
}
}
+1 -19
View File
@@ -1,27 +1,9 @@
//html {
// overflow-y: hidden;
//}
body {
font-family: "PT Sans", Arial, sans-serif;
margin: 0;
padding: 0;
}
.main {
margin-top: 5px;
.telephone {
font-size: 1.25em;
margin-left: 30px;
}
h1 {
text-align: right;
margin: 20px 50px 0 0;
font-weight: normal;
padding: 0;
}
min-width: 320px;
}
a {
+17 -1
View File
@@ -8,7 +8,7 @@
font-size: 13pt;
ul {
margin: 0 0 0 20px;
margin: 0 0 0 10px;
li {
display: inline-block;
@@ -62,3 +62,19 @@
}
}
@media screen and (max-device-width: 500px){
.menu {
font-size: 10pt;
ul {
margin: 0 0 0 5px;
padding: 0 0 0 0;
li {
display: inline-block;
padding: 3px 3px 10px 3px;
margin: 0 4px 5px 0;
}
}
}
}
+13 -1
View File
@@ -15,6 +15,10 @@
padding-bottom: 50px;
text-align: center;
.schedule-block{
overflow-x: scroll;
}
table{
position: relative;
margin: 30px auto 0 auto;
@@ -196,4 +200,12 @@
display: block;
margin-top: 90px;
}
}
}
@media screen and (max-device-width: 400px){
.schedule{
thead.fix{
display: none;
}
}
}
+46 -2
View File
@@ -1,9 +1,9 @@
.tape-block{
width: 70%;
max-width: 700px;
max-width: 800px;
min-width: 300px;
margin: 100px auto 100px;
margin: 50px auto 100px;
}
.tape-block-content{
@@ -40,4 +40,48 @@
right: -25px;
background-image: url(/graphics/tape-rb.png);
}
}
@media screen and (max-device-width: 400px) {
.tape-block {
width: 70%;
max-width: 250px;
min-width: 200px;
margin: 50px auto 100px;
}
.tape-block-content {
.tape {
width: 62px;
height: 62px;
position: absolute;
z-index: 10;
}
.tape-tl {
top: -20px;
left: -20px;
background-image: url(/graphics/m-tape-tl.png);
background-size: 100%;
}
.tape-tr {
top: -20px;
right: -20px;
background-image: url(/graphics/m-tape-tr.png);
}
.tape-bl {
bottom: 10px;
left: -20px;
background-image: url(/graphics/m-tape-bl.png);
}
.tape-br {
bottom: 10px;
right: -20px;
background-image: url(/graphics/m-tape-br.png);
}
}
}
+1 -7
View File
@@ -1,5 +1,5 @@
.timeline {
.post {
.timeline-record {
.user{
margin-top: 4px;
@@ -22,12 +22,6 @@
}
.body{
padding: 20px 20px 50px;
// padding: 12px 0 0;
// h2{
//
// }
a{
border-bottom: none;
}
+70 -82
View File
@@ -1,103 +1,91 @@
.timeline{
min-width: 500px;
min-width: 400px;
position: relative;
margin: 0 0 50px;
display: block;
width: 75%;
margin: 0 auto 50px;
}
&:before{
content: '';
width: 10px;
height: 10px;
position: absolute;
background-color: black;
top: 0;
left: calc(50% - 6px);
border-radius: 50%;
z-index: 1;
.timeline-record{
position: relative;
.body {
margin: 0 0 50px;
img{
margin: 0 auto;
display: block;
min-height: 500px;
}
}
}
.post{
position: relative;
display: flex;
.head, .body{
@media screen and (max-device-width: 400px) {
.timeline {
min-width: 0;
position: relative;
width: 50%;
box-sizing: border-box;
}
.head {
padding: 25px 20px;
}
.body {
padding: 0 20px;
}
&.left{
flex-flow: row-reverse;
.body{
text-align: right;
}
margin: 0 0 50px;
.head{
text-align: left;
margin: 0;
padding: 0;
}
.body:after{
content: '';
position: absolute;
width: 12px;
height: calc(100% - 98px);
top: 98px;
right: 0;
background: url(/graphics/timeline-line.png) no-repeat right;
background-size: 2px 100%;
}
.head:after{
content: '';
position: absolute;
width: 12px;
height: 98px;
top: 0;
left: -12px;
background: url(/graphics/timeline-arrow-left.png) no-repeat;
}
}
&.right{
flex-flow: row;
.body{
margin: 0 0 40px;
padding: 0;
}
.body p{
text-align: left;
margin: 0 0 2px;
padding: 0;
}
.head{
text-align: right;
margin: 0 10px;
.timeline-record {
position: relative;
display: flex;
.head, .body {
position: relative;
width: 90%;
box-sizing: border-box;
}
.head {
padding: 5px 20px;
}
.body {
padding: 0 20px;
}
}
}
}
.timeline-end{
width: 50%;
margin: 0 auto;
text-align: center;
button.more{
position: relative;
top: -2px;
width: 100px;
height: 40px;
border: 2px solid black;
padding: 0 10px;
background: none;
font-size: 14pt;
&:hover{
background: gainsboro;
}
.body:after{
content: '';
position: absolute;
width: 100px;
height: calc(100% - 98px);
top: 98px;
left: -12px;
background: url(/graphics/timeline-line.png) no-repeat;
background-size: 2px 100%;
}
.head:after{
content: '';
position: absolute;
width: 12px;
height: 98px;
&:active{
top: 0;
left: calc(100% - 2px);
background: url(/graphics/timeline-arrow-right.png) no-repeat;
}
}
}
-140
View File
@@ -1,140 +0,0 @@
/**
* Created by tmshv on 22/11/14.
*/
var config = require("../config");
var db = require("../core/db");
var instagram = require("../core/instagram");
var express = require("express");
var Promise = require("promise");
var methodOverride = require("method-override");
var logger = require("morgan");
var cookieParser = require("cookie-parser");
var bodyParser = require("body-parser");
var Post = require("../schema/post");
db.init(config.db)
.then(function () {
server(config.port);
});
function server(port) {
var app = express();
app.use(logger("dev"));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(methodOverride());
require("../routers/instagram")(app);
var Router = express.Router;
var instagram = require("../core/instagram");
var router = new Router();
router.route("/").get(function (req, res) {
if ("instagram_code" in req.cookies) {
var client = instagram.client(req.cookies["instagram_code"]);
instagramSandbox(client, res);
} else {
var ig = instagram.client();
var url = ig.get_authorization_url(config.instagram.redirect_uri, {scope: ["basic"], state: "hello"});
res.redirect(url);
}
});
app.use(router);
app.listen(port);
}
function instagramSandbox(ig, res) {
// //{"username":"mlazareffa","bio":"","website":"","profile_picture":"http://images.ak.instagram.com/profiles/anonymousUser.jpg","full_name":"","id":"1549382451"}
// //ig.user_search("mlazareffa", [], function(err, users, remaining, limit) {
// // console.log(err, users, remaining, limit);
// // res.json(users);
// //});
//
// // ig.user_media_recent("1549382451", [], function (err, medias, pagination, remaining, limit) {
// // console.log(err, medias, pagination, remaining, limit);
// // res.json(users);
// // });
//
// //ig.subscriptions(function(err, result, remaining, limit){
// // console.log(err, result, remaining, limit);
// // res.json(result);
// //});
//
// //ig.del_subscription({id: 14180526}, function (err, subscriptions, limit) {
// // console.log(err, subscriptions, limit);
// // res.json(subscriptions);
// //});
//
// ///* OPTIONS: { [verify_token] }
// // ig.add_tag_subscription("hello", "http://home.tmshv.ru:1337/instagram/tag/hello", [], function(err, result, remaining, limit){
// // console.log(err, result, remaining, limit);
// // res.json(result);
// //});
findByTag(ig, "shlb_hudozka", 50)
.catch(function (error) {
console.log(error);
})
.then(function (params) {
var list = params.medias;
var pagination = params.pagination;
var remaining = params.remaining;
var limit = params.limit;
var posts = list.map(function (gram) {
//var post = new Post();
var post = {};
post.id = gram.id;
post.author = gram.user["username"];
post.publishDate = new Date(parseInt(gram["created_time"]) * 1000);
post.data = gram;
post.body = "";
post.type = "instagram";
return post;
});
Promise.all(posts.map(function (post) {
return new Promise(function (resolve, reject) {
console.log('updating', post.id);
Post.update({id: post.id}, post, {upsert: true}, function (error, num) {
if (error) {
reject(error);
} else {
resolve();
}
});
});
}))
.catch(function (error) {
console.log(error);
})
.then(function () {
res.send("LOL");
});
//if (pagination.next) {
// pagination.next(mtr); // Will get second page results
//}
});
}
function findByTag(ig, tag, count) {
return new Promise(function (resolve, reject) {
ig.tag_media_recent(tag, {count: count}, function (err, medias, pagination, remaining, limit) {
if (err) {
reject(err);
} else {
resolve({
medias: medias,
pagination: pagination,
remaining: remaining,
limit: limit
});
}
});
});
}
+2
View File
@@ -5,8 +5,10 @@
var config = require("../config");
var db = require("../core/db");
var server = require("../server");
var instagram = require("../instagram");
db.init(config.db.uri)
//.then(instagram)
.then(function () {
server(config.port);
});
+3 -1
View File
@@ -25,6 +25,8 @@
"angular-route": "~1.3.3",
"angular-animate": "~1.3.3",
"angular": "~1.3.3",
"angulartics": "~0.17.2"
"angulartics": "~0.17.2",
"angular-spinner": "~0.6.1",
"socket.io-client": "~1.3.5"
}
}
+4 -2
View File
@@ -2,12 +2,14 @@
* Created by tmshv on 22/11/14.
*/
var query = require("../../utils/net").query;
function APIFeed(http){
this.request = http;
}
APIFeed.prototype.feed = function() {
return this.request.get("/news");
APIFeed.prototype.feed = function(count, portion) {
return this.request.get("/news?"+query([["count", count], ["portion", portion]]));
};
module.exports = APIFeed;
+14 -2
View File
@@ -6,7 +6,8 @@ var app = angular.module("hudozhka", [
"hudozhka.data",
"ngRoute",
"angulartics",
"angulartics.google.analytics"
"angulartics.google.analytics",
"angularSpinner"
]);
app.config(function ($locationProvider, $routeProvider) {
@@ -49,15 +50,26 @@ app.config(function ($locationProvider, $routeProvider) {
});
});
app.run(function($location, $rootScope, $http) {
app.run(function($location, $rootScope, $http, config) {
$rootScope.$on("$routeChangeSuccess", function (event, current) {
$rootScope.title = current["$$route"].title;
});
$rootScope.contact = {
address: config.address,
telephone: config.telephone,
email: config.email
};
$rootScope.now = {
year: new Date().getFullYear()
};
$http.defaults.headers.common["Accept"] = "application/json";
});
require("./api/api")(app);
require("./services/io")(app);
require("./ui/menu")(app);
require("./ui/timeline")(app);
require("./filters/uppercase-first")(app);
+3 -1
View File
@@ -14,6 +14,8 @@ angular.module("hudozhka.data", [])
})
.service("config", function(){
return {
telephone: "8 (81362) 77-502"
telephone: "8 (81362) 76-312",
email: "hudozka@gmail.com",
address: "г. Шлиссельбург, ул. 18-го января, д. 3"
};
});
+28
View File
@@ -0,0 +1,28 @@
/**
* Created by tmshv on 06/11/14.
*/
angular.module("hudozhka.instagram", [])
.controller("InstagramController", function($scope, $http, $window){
//$scope.auth = function() {
// $http.get("/instagram/auth/url")
// .success(function (data) {
// $window.location.href = data.url;
// });
//};
$http.get("/instagram/user")
.error(function() {
})
.success(function (user) {
$scope.user = user;
});
$scope.invite = function() {
$http.get("/instagram/invite")
.success(function (data) {
$scope.inviteCode = data.code;
});
};
});
-1
View File
@@ -5,7 +5,6 @@
module.exports = function (app) {
app.controller("HomePageController", function ($scope, config) {
$scope.pageClass = "page-home";
$scope.telephone = config.telephone;
$(".fotorama").fotorama();
});
+11
View File
@@ -0,0 +1,11 @@
/**
* Created by tmshv on 15/03/15.
*/
module.exports = function (app) {
var socket = io();
app.service("io", function(){
return socket;
})
};
+99 -14
View File
@@ -28,6 +28,22 @@ function postText(post){
module.exports = function(app) {
app.directive("timeline", function (team) {
function toInstagram(post){
var author_id = personByInstagram(team.team, post.data.author);
var name = author_id ? team.short(author_id) : post.data.author;
return {
date: post.date,
image: post.data.image.standard_resolution.url,
url: post.data.url,
username: name,
//userpic: post.data.user.profile_picture,
text: post.body,
//text: postText(post),
type: post.type
};
}
return {
templateUrl: "/views/timeline.html",
scope: {
@@ -38,23 +54,92 @@ module.exports = function(app) {
return index % 2 === 1;
}
},
controller: function($scope, api){
api.news.feed()
.success(function (list) {
$scope.feed = list.map(function (post) {
var author_id = personByInstagram(team.team, post.data.user.username);
var name = author_id ? team.short(author_id) : post.data.user.username;
controller: function($scope, $timeout, usSpinnerService, io, api){
var portion = 0;
var count = 10;
$scope.feed = [];
return {
date: post.publishDate,
image: post.data.images.standard_resolution.url,
url: post.data.link,
username: name,
userpic: post.data.user.profile_picture,
text: postText(post)
};
$scope.timelineUpdating = false;
usSpinnerService.stop("timelineMore");
//usSpinnerService.spin("timelineMore");
$scope.recordClass = function (i) {
return i['type'];
};
$scope.loadNext = function () {
$scope.timelineUpdating = true;
usSpinnerService.spin("timelineMore");
api.news.feed(count, portion)
.error(function(error) {
console.log(error);
})
.success(function (list) {
$scope.timelineUpdating = false;
usSpinnerService.stop("timelineMore");
//$timeout(function () {
//
//}, 5000);
var feed = list.map(function (post) {
if(post.type == "instagram") return toInstagram(post);
else return post;
});
portion++;
$scope.feed = $scope.feed.concat(feed);
});
};
$scope.loadNext();
io.on("post", function (params) {
var posts = params instanceof Array ? params : [params];
console.log("post", posts);
var feed = posts.map(function (post) {
if(post.type == "instagram") return toInstagram(post);
else return post;
});
$scope.$apply(function () {
$scope.feed = feed.concat($scope.feed);
});
});
}
};
});
app.directive("timelineRecord", function ($compile, $http, $sce, team) {
var templates = {
"post": ["/views/timeline-post.html", linkPost],
"instagram": ["/views/timeline-gram.html", linkGram]
};
function linkPost(scope, element, attrs) {
scope.message = $sce.trustAsHtml(scope.post.body);
}
function linkGram(scope, element, attrs) {
}
return {
restrict: "E",
scope: {
post:"=content"
},
link: function(scope, element, attrs){
var type = scope.post.type;
if(type in templates) {
$http.get(templates[type][0])
.success(function (tpl) {
element.html(tpl).show();
$compile(element.contents())(scope);
templates[type][1](scope, element, attrs);
});
}
}
};
});
+2 -3
View File
@@ -10,6 +10,7 @@ var privateFile = process.env["PRIVATE"] || "private.json";
var privateData = JSON.parse(fs.readFileSync(privateFile, "utf-8"));
var config = {
defaultIndex: "/templates/index.html" || process.env["INDEX"],
port: process.env["PORT"] || 3000,
pub: "./",
data: {
@@ -21,9 +22,7 @@ var config = {
db: {
uri: "mongodb://localhost:27017/hudozka"
},
tags: ["shlb_hudozka"]
}
};
module.exports = Object.keys(privateData)
-46
View File
@@ -1,46 +0,0 @@
/**
* Created by tmshv on 22/11/14.
*/
var config = require("../config");
var Promise = require("promise");
var auth_clients = {};
module.exports = {
client: function(param){
if(param in auth_clients) {
return auth_clients[param];
}else{
return createClient();
}
},
authorize: function(code){
return new Promise(function(resolve, reject){
var api = createClient();
api.authorize_user(code, config.instagram.redirect_uri, function (err, result) {
if (err) return reject(err);
else {
var token = result.access_token;
var c = createClient(token);
auth_clients[code] = c;
resolve(c);
}
});
});
}
};
function createClient(token) {
var api = require('instagram-node').instagram();
if (token) {
api.use({access_token: token});
} else {
api.use({
client_id: config.instagram.client_id,
client_secret: config.instagram.client_secret
});
}
return api;
}
+7
View File
@@ -50,6 +50,13 @@ gulp.task("compile", function(){
}))
.pipe(uglify())
.pipe(gulp.dest("public"));
gulp.src("client/instagram.js")
.pipe(browserify({
transform: [annotate]
}))
.pipe(uglify())
.pipe(gulp.dest("public"));
});
gulp.task("imagemin", function(){
+37
View File
@@ -0,0 +1,37 @@
/**
* Created by tmshv on 12/03/15.
*/
var db = require("../core/db");
var co = require("co");
var instagram = require("./instagram");
var config = require("../config");
module.exports = function () {
return loadUsers()
.then(updateSubscription)
};
function loadUsers() {
return new Promise(function (resolve, reject) {
db.c("users").find({provider: "instagram"})
.toArray()
.then(function (users) {
users.forEach(function (u) {
return instagram.initUser(u);
});
return users;
})
.then(resolve);
});
}
function updateSubscription() {
var tags = config.instagram["tags"];
return tags.map(function (tag) {
var cb = config.instagram["tag_callback"];
return co(function *() {
return yield instagram.api.subscribe(tag, cb);
})
});
}
+172
View File
@@ -0,0 +1,172 @@
/**
* Created by tmshv on 22/11/14.
*/
var EventEmitter = require("events").EventEmitter;
var thunkify = require("thunkify");
var config = require("../config");
var db = require("../core/db");
var instagram = require("instagram-node");
function Instagram(options) {
this.client_id = options.client_id;
this.client_secret = options.client_secret;
this.redirect_uri = options.redirect_uri;
this.default_user = options.default_user;
this.clients = {};
this.users = {};
EventEmitter.call(this);
}
Instagram.prototype = Object.create(EventEmitter.prototype);
Instagram.prototype.authorizationURL = function (scope, state) {
var params = {};
params.scope = scope || ["basic"];
if (state) {
params.state = state;
}
var client = createClient();
return client["get_authorization_url"](this.redirect_uri, params);
};
Instagram.prototype.addClient = function *(code, params) {
var token = params.access_token;
var item = params.user;
item.code = code;
item.access_token = token;
item.provider = "instagram";
yield db.c("users").update({provider: "instagram", id: params.user.id}, item, {upsert: true});
return this.initUser(item);
};
Instagram.prototype.initUser = function (user) {
var token = user.access_token;
this.clients[user.code] = createClient(token);
this.users[user.code] = user;
return this;
};
Instagram.prototype.getUsers = function () {
var users = this.users;
return Object.keys(users)
.map(function (code) {
return users[code];
});
};
Instagram.prototype.update = function (body) {
this.emit("update", body);
};
Instagram.prototype.client = function (code) {
if (code && code in this.clients) {
return this.clients[code];
} else {
return createClient();
}
};
Instagram.prototype.user = function (code) {
if (code && code in this.users) {
return this.users[code];
} else {
return null;
}
};
Instagram.prototype.authorize = function *(code) {
var api = createClient();
var authorize = thunkify(api["authorize_user"]);
var result = yield authorize(code, this.redirect_uri);
if (result) {
yield this.addClient(code, result);
}
return result;
};
Instagram.prototype.getUser = function *() {
if (this.default_user) {
var du = yield db.c("users").findOne({username: this.default_user});
if (du) {
return du;
}
}
return yield db.c("users").findOne({provider: "instagram"});
};
Instagram.prototype.getUsers = function *() {
return yield db.c("users").find({provider: "instagram"}).toArray();
};
Instagram.prototype.api = {
subscriptions: function *() {
var ig = createClient();
var subs = thunkify(ig["subscriptions"]);
try {
var s = yield subs();
return s[0];
} catch (error) {
return null;
}
},
subscribe: function *(tag, callbackURL) {
var ig = createClient();
var sub = thunkify(ig["add_tag_subscription"]);
try {
var s = yield sub(tag, callbackURL);
return s[0];
} catch (error) {
return null;
}
},
unsubscribe: function *(id) {
var ig = createClient();
var sub = thunkify(ig["del_subscription"]);
try {
var s = yield sub({id: id});
return s[0];
} catch (error) {
return null;
}
},
tagMediaRecent: function *(client, tag, count) {
var tag_media_recent = thunkify(client["tag_media_recent"]);
try{
var result = yield tag_media_recent(tag, {count: count});
return {
medias: result[0],
pagination: result[1],
remaining: result[2],
limit: result[3]
}
}catch(error){
return null;
}
}
};
module.exports = new Instagram(config.instagram);
function createClient(token) {
var client = instagram.instagram({}, {});
if (token) {
client.use({access_token: token});
} else {
client.use({
client_id: config.instagram.client_id,
client_secret: config.instagram.client_secret
});
}
return client;
}
+16
View File
@@ -0,0 +1,16 @@
/**
* Created by tmshv on 14/03/15.
*/
var publisher = require("./publish");
module.exports = function (app) {
app.io.use(function *(next) {
publisher.on("post", function (post) {
console.log("IO POST", post);
app.io.emit("post", post);
});
yield* next;
});
};
+97
View File
@@ -0,0 +1,97 @@
/**
* Created by tmshv on 10/03/15.
*/
var co = require("co");
var util = require("util");
var EventEmitter = require("events").EventEmitter;
var instagram = require("./instagram");
var config = require("../config");
var db = require("../core/db");
function Publisher() {
EventEmitter.call(this);
var self = this;
instagram.on("update", function (data) {
var tag = config.instagram["tags"][0];
findInstagrams(tag)
.catch(function (error) {
console.log(error);
})
.then(function (posts) {
var ids = posts.map(function (gram) {
return gram.data.id;
});
return uploadInstagrams(posts)
.then(function () {
return db.c("posts").find({"data.id": {$in: ids}}).toArray();
});
})
.then(function (posts) {
self.emit("post", posts);
});
});
}
util.inherits(Publisher, EventEmitter);
module.exports = new Publisher();
function *fbt(client, tag) {
var param = yield instagram.api.tagMediaRecent(client, tag, 10);
return param.medias.map(toInstagram);
}
function toInstagram(gram) {
var post = {};
try {
post.body = gram.caption.text;
} catch (error) {
post.body = "";
}
post.type = "instagram";
post.tags = gram.tags;
post.date = new Date(parseInt(gram["created_time"]) * 1000);
post.data = {
id: gram.id,
author: gram.user["username"],
image: gram.images,
url: gram.link
};
return post;
}
function findInstagrams(tag){
return co(function *() {
var user = yield instagram.getUser();
if (user) {
var client = instagram.client(user.code);
var permitted_users = yield instagram.getUsers();
permitted_users = permitted_users.map(function (user) {
return user["username"];
});
var medias = yield fbt(client, tag);
//medias = medias.filter(function (gram) {
// return permitted_users.indexOf(gram.data.author) > -1;
//});
return medias;
}
});
}
function uploadInstagrams(list){
return Promise.all(
list.map(function (g) {
return db.c("posts").update({"data.id": g.data.id}, g, {upsert: true});
})
);
}
+162
View File
@@ -0,0 +1,162 @@
/**
* Created by tmshv on 22/11/14.
*/
var path = require("path");
var route = require("koa-route");
var router = require("../routes");
var instagram = require("../instagram/instagram");
module.exports = function (app) {
app.use(function *(next) {
var code = this.cookies.get("instagram_code");
if (code) {
var client = instagram.client(code);
var user = instagram.user(code);
if (client && user) {
this.instagram = {
client: client,
user: user
}
}
}
yield* next;
});
app.use(
route.get("/instagram", function *() {
var invite = this.cookies.get("invite_code") || this.query.code;
if(!this.instagram) {
if(invite == undefined){
this.body = "invite required";
this.status = 401;
}else if(invite == "LOL"){
this.cookies.set("invite_code", invite, {expires: expire()});
//todo: invalidate invite
yield router.index(
path.join(__dirname, "../templates/instagram.html")
);
}else{
this.body = "invite ist correct";
this.status = 401;
}
}else{
yield router.index(
path.join(__dirname, "../templates/instagram.html")
);
}
})
);
app.use(
route.get("/instagram/auth", function *() {
var invite = this.cookies.get("invite_code");
if(invite) {
var url = instagram.authorizationURL(null, "/instagram");
this.redirect(url);
}else{
this.status = 401;
this.body = "invite required";
}
})
);
app.use(
route.get("/instagram/user", function *() {
var code = this.cookies.get("instagram_code");
var user = instagram.user(code);
if(user) {
this.body = user;
}else{
this.status = 404;
}
})
);
app.use(
route.get("/instagram/auth/callback", function *() {
var state = this.query.state || "/";
var code = this.query.code;
var client = yield instagram.authorize(code);
if (client) {
this.cookies.set("instagram_code", code, {expires: expire()});
this.redirect(state);
} else {
this.status = 401;
this.redirect(state);
}
})
);
app.use(route.get("/instagram/subscription/list", function *() {
var result = yield instagram.api.subscriptions();
if(result) {
this.body = result;
}else{
this.status = 500;
}
}));
app.use(route.get("/instagram/subscription/add", function *() {
var tag = this.query.tag;
var cu = this.query.url;
var result = yield instagram.api.subscribe(tag, cu);
if(result) {
this.body = result;
}else{
this.status = 500;
}
}));
app.use(route.get("/instagram/subscription/delete", function *() {
var id = this.query.id;
var result = yield instagram.api.unsubscribe(id);
if(result) {
this.body = result;
}else{
this.status = 500;
}
}));
app.use(route.get("/instagram/callback/:rnd", function *() {
if(this.query["hub.mode"] == "subscribe"){
this.body = this.query["hub.challenge"];
}else{
this.status = 400;
}
}));
app.use(route.post("/instagram/callback/:rnd", function *(rnd) {
var sign = this.header["x-hub-signature"];
//console.log(this.headers);
var body = this.request.body;
//var hmac = crypto.createHmac("sha1", instagram.client_secret);
//hmac.update(body);
//var shasum = hmac.digest("hex");
//console.log("X-Hub-Signature", sign);
//console.log("Hmac", shasum);
//console.log();
//if(shasum.digest("hex") == sign) {
instagram.update(body);
//}
this.body = "";
}));
};
function expire(time){
return time || new Date(Date.now() + 1000 * 60 * 60 * 24 * 7);
}
+14 -1
View File
@@ -5,7 +5,11 @@ server {
server_name art.shlisselburg.org;
location / {
proxy_pass http://localhost:18010;
proxy_pass http://hudozka;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
@@ -19,3 +23,12 @@ server {
server_name art.shburg.org;
return 301 $scheme://art.shlisselburg.org$request_uri;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream hudozka {
server localhost:18010;
}
+8 -5
View File
@@ -1,9 +1,9 @@
{
"name": "app",
"name": "Hudozka",
"private": true,
"version": "2.0.0",
"version": "3.1.0",
"description": "",
"main": "main.js",
"main": "bin/www.js",
"scripts": {
"test": "mocha"
},
@@ -14,8 +14,9 @@
"author": "Roman Timashev",
"license": "ISC",
"dependencies": {
"co": "^4.4.0",
"instagram-node": "^0.5.1",
"koa": "^0.18.0",
"koa-bodyparser": "^1.4.1",
"koa-conditional-get": "^1.0.2",
"koa-etag": "^2.0.0",
"koa-helmet": "0.0.3",
@@ -24,8 +25,10 @@
"koa-route": "^2.4.0",
"koa-static": "^1.4.9",
"koa-useragent": "0.0.5",
"koa.io": "0.0.3",
"mz": "^1.3.0",
"promised-mongo": "^0.11.1"
"promised-mongo": "^0.11.1",
"thunkify": "^2.1.2"
},
"devDependencies": {
"bower": "^1.3.12",
+2 -1
View File
@@ -4,6 +4,7 @@
var path = require("path");
var fs = require("mz/fs");
var config = require("../config");
function accepts(routes, def) {
return function *() {
@@ -26,7 +27,7 @@ function accepts(routes, def) {
function index(filename) {
if (!filename){
filename = path.join(__dirname, "../templates/index.html");
filename = path.join(__dirname, "..", config.defaultIndex);
}
return function *() {
-42
View File
@@ -1,42 +0,0 @@
/**
* Created by tmshv on 22/11/14.
*/
var Router = require("express").Router;
var instagram = require("../core/instagram");
module.exports = function (app) {
var router;
router = new Router();
router.route("/auth/instagram/callback")
.get(function (req, res) {
var code = req.query.code;
instagram.authorize(code)
.catch(function(error){
console.log(error.body);
res.status(500).send('');
})
.then(function (client) {
res.cookie("instagram_code", code);
res.redirect("/");
});
});
app.use(router);
//http://your-callback.com/url/?hub.mode=subscribe&hub.challenge=15f7d1a91c1f40f8a748fd134752feb3&hub.verify_token=myVerifyToken
router = new Router();
router.route("/instagram/tag/:tag")
.get(function (req, res) {
var hub_challenge = req.query["hub.challenge"];
//var hub_verify_token = req.query["hub.verify_token"];
console.log("real time get", req.param("tag"), hub_challenge);
res.send(hub_challenge);
})
.post(function (req, res) {
console.log("real time tag", req.param("tag"));
console.log(req.body);
res.send("");
});
app.use(router);
};
+84 -4
View File
@@ -3,10 +3,90 @@
*/
var route = require("koa-route");
var router = require("./");
var db = require("../core/db");
module.exports = function (app) {
app.use(route.get("/news", function *(){
this.body = yield db.c("posts").find().toArray();
}));
};
app.use(route.get("/news", router.accepts({
"text/html": function *() {
this.redirect("/");
},
"text/plain": function *() {
this.redirect("/");
},
"application/json": function *() {
var count = parseInt(this.query["count"]) || 10;
var portion = parseInt(this.query["portion"]) || 0;
var skip = portion * count;
var query = {};
if (this.query.type) query.type = this.query.type;
var pinned = [];
if(portion == 0) {
var now = new Date();
pinned = yield db.c("posts").find({until: {$gte: now}}).toArray()
.then(function (items) {
return items.sort(sortNewsByDate);
});
}
var pinned_ids = pinned.map(function (p) {
return p["_id"]+"";
});
var posts = yield db.c("posts").find(query)
.sort({date: -1})
.skip(skip)
.limit(count)
.toArray()
.then(function (items) {
return items.filter(function (i) {
var id = i["_id"]+"";
return pinned_ids.indexOf(id) < 0;
});
});
this.body = pinned.concat(posts);
//this.body = pinned_ids
}
})));
app.use(route.get("/news/pinned", router.accepts({
"text/html": function *() {
this.redirect("/");
},
"text/plain": function *() {
this.redirect("/");
},
"application/json": function *() {
var now = new Date();
var pinned = yield db.c("posts").find({until: {$gte: now}}).toArray()
.then(function (items) {
return items.sort(sortNewsByDate);
});
this.body = pinned;
}
})));
app.use(route.get("/news/:uri", router.accepts({
"text/html": router.index(),
"text/plain": router.index(),
"application/json": function *(uri) {
var item = yield db.c("posts").findOne({uri: uri});
if (item) {
this.body = item;
} else {
this.status = 404;
}
}
})));
};
function sortNewsByDate(i1, i2) {
var t1 = new Date(i1.date).getTime();
var t2 = new Date(i2.date).getTime();
if (t1 < t2) return 1;
if (t1 > t2) return -1;
return 0;
}
+7 -2
View File
@@ -1,13 +1,14 @@
var path = require("path");
var koa = require("koa");
var koa = require("koa.io");
var route = require("koa-route");
var serve = require("koa-static");
var logger = require("koa-logger");
var conditional = require("koa-conditional-get");
var etag = require("koa-etag");
var prerender = require("koa-prerender");
var helmet = require('koa-helmet');
var helmet = require("koa-helmet");
var bodyParser = require("koa-bodyparser");
var config = require("./config");
var routes = require("./routes");
@@ -15,6 +16,7 @@ var routes = require("./routes");
var app = koa();
app.proxy = true;
app.use(bodyParser());
app.use(logger());
app.use(conditional());
app.use(etag());
@@ -55,6 +57,9 @@ require("./routes/news")(app);
require("./routes/404")(app);
require("./instagram/router")(app);
require("./instagram/io")(app);
if (process.env["NODE_ENV"] === "development") {
app.use(route.get("/debug", function *() {
var out = {};
+86
View File
@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html ng-app="hudozhka">
<head>
<base href="/">
<meta name="fragment" content="!">
<meta name="google-site-verification" content="8BxOTw-Q02DS2KAdcGcnIMwiPZ58DVB18XpOfRibCcg">
<meta name="viewport" content="width=device-width, maximum-scale=1.0" />
<title ng-bind="title">ДШХ Шлиссельбурга</title>
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/animate.min.css">
<link rel="stylesheet" href="/fonts/stylesheet.css">
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/bower_components/angular-animate/angular-animate.min.js"></script>
<script src="/bower_components/angulartics/dist/angulartics.min.js"></script>
<script src="/bower_components/angulartics/dist/angulartics-ga.min.js"></script>
<script src="/bower_components/spin.js/spin.js"></script>
<script src="/bower_components/angular-spinner/angular-spinner.min.js"></script>
<script src="/bower_components/socket.io-client/socket.io.js"></script>
<link rel="stylesheet" href="/bower_components/fotorama/fotorama.css">
<script src="/bower_components/fotorama/fotorama.js"></script>
<script src="/data.js"></script>
<script src="/app.js"></script>
</head>
<body>
<div class="menu" ng-controller="MenuController">
<ul>
<li ng-repeat="item in menu" class="{{item.color}}" ng-class="{selected:isCurrent(item)}">
<span ng-hide="isValid(item)">{{item.text}}</span>
<a href="{{item.url}}" ng-show="isValid(item)">{{item.text}}</a>
</li>
<!--<a href="{{vkgroup}}" class="vk"><img src="/graphics/icon.vk.png"></a>-->
</ul>
</div>
<div class="page {{pageClass}}" ng-view></div>
<footer>
<div class="footer-content">
<div class="info-block">
<div>
<h4>Ссылки на образовательные сайты</h4>
<ul>
<li><a href="http://минобрнауки.рф">минобрнауки.рф</a> — Министерство образования и науки Российской Федерации</li>
<li><a href="http://edu.ru">edu.ru</a> — Федеральный сайт «Российское образование»</li>
<li><a href="http://window.edu.ru">window.edu.ru</a> — Единое окно доступа к образовательным ресурсам</li>
<li><a href="http://school-collection.edu.ru">school-collection.edu.ru</a> — Единая коллекция цифровых образовательных ресурсов</li>
<li><a href="http://fcior.edu.ru">fcior.edu.ru</a> — Федеральный центр информационных образовательных ресурсов</li>
</ul>
<ul>
<li><a href="http://dkhshmga.ru">dkhshmga.ru</a> — Художественная школа Мги</li>
<li><a href="http://kirovskdmh.ucoz.ru">kirovskdmh.ucoz.ru</a> — Музыкальная школа Кировска</li>
</ul>
</div>
<div>
<h4>Документы</h4>
<ul>
<li><a target="_blank" href="/document/edu-license">Лицензия на осуществление образовательной деятельности</a></li>
<li><a target="_blank" href="/document/gov-certificate">Свидетельство о государственной регистрации права</a></li>
<li><a target="_blank" href="/document/EGRYL1">Свидетельство о внесении в «ЕГРЮЛ»</a></li>
<li><a target="_blank" href="/document/VAT">ИНН</a></li>
<li><a target="_blank" href="/document/statue-2013">Устав школы</a></li>
</ul>
</div>
</div>
<div class="info-block">
<div>
<p>© 2014...{{now.year}}</p>
<p>Художественная школа Шлиссельбурга</p>
<p>Адрес: {{contact.address}}</p>
<p>Телефон: {{contact.telephone}}</p>
<p>Почта: <a href="mailto:{{contact.email}}">{{contact.email}}</a></p>
</div>
</div>
</div>
</footer>
</body>
</html>
+40 -28
View File
@@ -4,6 +4,7 @@
<base href="/">
<meta name="fragment" content="!">
<meta name="google-site-verification" content="8BxOTw-Q02DS2KAdcGcnIMwiPZ58DVB18XpOfRibCcg">
<meta name="viewport" content="width=device-width, maximum-scale=1.0" />
<title ng-bind="title">ДШХ Шлиссельбурга</title>
@@ -17,6 +18,9 @@
<script src="/bower_components/angular-animate/angular-animate.min.js"></script>
<script src="/bower_components/angulartics/dist/angulartics.min.js"></script>
<script src="/bower_components/angulartics/dist/angulartics-ga.min.js"></script>
<script src="/bower_components/spin.js/spin.js"></script>
<script src="/bower_components/angular-spinner/angular-spinner.min.js"></script>
<script src="/bower_components/socket.io-client/socket.io.js"></script>
<link rel="stylesheet" href="/bower_components/fotorama/fotorama.css">
<script src="/bower_components/fotorama/fotorama.js"></script>
@@ -48,44 +52,52 @@
<span ng-hide="isValid(item)">{{item.text}}</span>
<a href="{{item.url}}" ng-show="isValid(item)">{{item.text}}</a>
</li>
<a href="{{vkgroup}}" class="vk"><img src="/graphics/icon.vk.png"></a>
<!--<a href="{{vkgroup}}" class="vk"><img src="/graphics/icon.vk.png"></a>-->
</ul>
</div>
<div class="page {{pageClass}}" ng-view></div>
<footer>
<div class="info-block">
<div>
<h4>Ссылки на образовательные сайты</h4>
<ul>
<li><a href="http://минобрнауки.рф">минобрнауки.рф</a> — Министерство образования и науки Российской Федерации</li>
<li><a href="http://edu.ru">edu.ru</a> — Федеральный сайт «Российское образование»</li>
<li><a href="http://window.edu.ru">window.edu.ru</a> — Единое окно доступа к образовательным ресурсам</li>
<li><a href="http://school-collection.edu.ru">school-collection.edu.ru</a> — Единая коллекция цифровых образовательных ресурсов</li>
<li><a href="http://fcior.edu.ru">fcior.edu.ru</a> — Федеральный центр информационных образовательных ресурсов</li>
</ul>
<ul>
<li><a href="http://dkhshmga.ru">dkhshmga.ru</a> — Художественная школа Мги</li>
<li><a href="http://kirovskdmh.ucoz.ru">kirovskdmh.ucoz.ru</a> — Музыкальная школа Кировска</li>
</ul>
<div class="footer-content">
<div class="info-block">
<div>
<h4>Ссылки на образовательные сайты</h4>
<ul>
<li><a href="http://минобрнауки.рф">минобрнауки.рф</a> — Министерство образования и науки Российской Федерации</li>
<li><a href="http://edu.ru">edu.ru</a> — Федеральный сайт «Российское образование»</li>
<li><a href="http://window.edu.ru">window.edu.ru</a> — Единое окно доступа к образовательным ресурсам</li>
<li><a href="http://school-collection.edu.ru">school-collection.edu.ru</a> — Единая коллекция цифровых образовательных ресурсов</li>
<li><a href="http://fcior.edu.ru">fcior.edu.ru</a> — Федеральный центр информационных образовательных ресурсов</li>
</ul>
<ul>
<li><a href="http://dkhshmga.ru">dkhshmga.ru</a> — Художественная школа Мги</li>
<li><a href="http://kirovskdmh.ucoz.ru">kirovskdmh.ucoz.ru</a> — Музыкальная школа Кировска</li>
</ul>
</div>
<div>
<h4>Документы</h4>
<ul>
<li><a target="_blank" href="/document/edu-license">Лицензия на осуществление образовательной деятельности</a></li>
<li><a target="_blank" href="/document/gov-certificate">Свидетельство о государственной регистрации права</a></li>
<li><a target="_blank" href="/document/EGRYL1">Свидетельство о внесении в «ЕГРЮЛ»</a></li>
<li><a target="_blank" href="/document/VAT">ИНН</a></li>
<li><a target="_blank" href="/document/statue-2013">Устав школы</a></li>
</ul>
</div>
</div>
<div>
<h4>Документы</h4>
<ul>
<li><a target="_blank" href="/document/edu-license">Лицензия на осуществление образовательной деятельности</a></li>
<li><a target="_blank" href="/document/gov-certificate">Свидетельство о государственной регистрации права</a></li>
<li><a target="_blank" href="/document/EGRYL1">Свидетельство о внесении в «ЕГРЮЛ»</a></li>
<li><a target="_blank" href="/document/VAT">ИНН</a></li>
<li><a target="_blank" href="/document/statue-2013">Устав школы</a></li>
</ul>
<div class="info-block">
<div>
<p>© 2014...{{now.year}}</p>
<p>Художественная школа Шлиссельбурга</p>
<p>Адрес: {{contact.address}}</p>
<p>Телефон: {{contact.telephone}}</p>
<p>Почта: <a href="mailto:{{contact.email}}">{{contact.email}}</a></p>
</div>
</div>
</div>
<div class="info-block">
<p>Художественная школа Шлиссельбурга, 2014 год</p>
</div>
</footer>
</body>
</html>
+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html ng-app="hudozhka.instagram">
<head>
<base href="/">
<meta name="fragment" content="!">
<meta name="viewport" content="width=device-width, maximum-scale=1.0" />
<title ng-bind="title">ДШХ Шлиссельбурга</title>
<link rel="stylesheet" href="/style.css">
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/instagram.js"></script>
</head>
<body ng-controller="InstagramController">
<div class="controls">
<a href="/instagram/auth" ng-show="!user">Instagram</a>
<a href="//instagram.com/{{user.username}}" ng-show="user">{{user.full_name}}</a>
<button ng-click="invite()">Invite</button>
{{inviteCode}}
</div>
</body>
</html>
+32 -32
View File
@@ -1,38 +1,38 @@
<div>
<div class="main">
<div class="block">
<span class="telephone">{{telephone}}</span>
<div class="main-block">
<div>
<!--&lt;!&ndash;<a href="tel://{{telephone}}"></a>&ndash;&gt;-->
<span class="telephone">{{contact.telephone}}</span>
<!--<ul class="submenu">-->
<!--<li><a href="/team#director">директор</a><p>М. Г. Тимашева</p></li>-->
<!--<li><a href="/enter">поступление</a></li>-->
<!--<li><a href="/contacts">контактная информация</a></li>-->
<!--<li><a href="/awards">награды</a></li>-->
<!--</ul>-->
</div>
<h1>«Художественная школа <strong>Шлиссельбурга</strong>»</h1>
<!--&lt;!&ndash;<ul class="submenu">&ndash;&gt;-->
<!--&lt;!&ndash;<li><a href="/team#director">директор</a><p>М. Г. Тимашева</p></li>&ndash;&gt;-->
<!--&lt;!&ndash;<li><a href="/enter">поступление</a></li>&ndash;&gt;-->
<!--&lt;!&ndash;<li><a href="/contacts">контактная информация</a></li>&ndash;&gt;-->
<!--&lt;!&ndash;<li><a href="/awards">награды</a></li>&ndash;&gt;-->
<!--&lt;!&ndash;</ul>&ndash;&gt;-->
</div>
<div class="tape-block">
<div class="tape-block-content">
<div class="tape tape-tl"></div>
<div class="tape tape-tr"></div>
<div class="tape tape-bl"></div>
<div class="tape tape-br"></div>
<div class="fotorama"
data-transition="crossfade"
data-autoplay="6000"
data-arrows="false"
data-width="100%"
data-fit="cover"
data-loop="true">
<img src="http://static.shlisselburg.org/art/graphics/sample2.jpg" alt="">
<img src="http://static.shlisselburg.org/art/graphics/sample4.jpg" alt="">
<img src="http://static.shlisselburg.org/art/graphics/sample5.jpg" alt="">
</div>
<h1>Шлиссельбургская детская художественная&nbsp;школа</h1>
</div>
<div class="tape-block">
<div class="tape-block-content">
<div class="tape tape-tl"></div>
<div class="tape tape-tr"></div>
<div class="tape tape-bl"></div>
<div class="tape tape-br"></div>
<div class="fotorama"
data-transition="crossfade"
data-autoplay="6000"
data-arrows="false"
data-width="100%"
data-fit="cover"
data-loop="true">
<img src="http://static.shburg.org/art/img/cat1.jpg" alt="">
<img src="http://static.shburg.org/art/img/cat2.jpg" alt="">
<img src="http://static.shburg.org/art/img/cat3.jpg" alt="">
</div>
</div>
</div>
<timeline></timeline>
</div>
<timeline></timeline>
+59 -47
View File
@@ -1,49 +1,61 @@
<div class="schedule" ng-controller="ScheduleController">
<p> Расписание {{sem}} семестра {{year}} года</p>
<table>
<thead class="">
<tr>
<th class="group">Гр.</th>
<th ng-class="{current: isToday(0)}">
<p class="day">Понедельник</p>
<p class="date">{{weekDay(0)}}</p>
</th>
<th ng-class="{current: isToday(1)}">
<p class="day">Вторник</p>
<p class="date">{{weekDay(1)}}</p>
</th>
<th ng-class="{current: isToday(2)}">
<p class="day">Среда</p>
<p class="date">{{weekDay(2)}}</p>
</th>
<th ng-class="{current: isToday(3)}">
<p class="day">Четверг</p>
<p class="date">{{weekDay(3)}}</p>
</th>
<th ng-class="{current: isToday(4)}">
<p class="day">Пятница</p>
<p class="date">{{weekDay(4)}}</p>
</th>
<th ng-class="{current: isToday(5)}">
<p class="day">Суббота</p>
<p class="date">{{weekDay(5)}}</p>
</th>
</tr>
</thead>
<tbody class="">
<tr ng-repeat="group in schedule">
<td class="group">
<p class="name">{{group.name}}</p>
<p class="time">{{group.time}}</p>
</td>
<div class="schedule" ng-controller="ScheduleController">
<p> Расписание {{sem}} семестра {{year}} года</p>
<div class="schedule-block">
<table>
<thead class="">
<tr>
<th class="group">Гр.</th>
<th ng-class="{current: isToday(0)}">
<p class="day">Понедельник</p>
<td ng-repeat="day in group.days track by $index" ng-class="{current: isToday($index)}">
<p class="lesson"><a href="">{{day.lesson}}</a></p>
<p class="teacher"><a href="">{{day.teacher}}</a></p>
<p class="time">{{day.time[0]}}</p>
<p class="time">{{day.time[1]}}</p>
</td>
</tr>
</tbody>
</table>
<p class="date">{{weekDay(0)}}</p>
</th>
<th ng-class="{current: isToday(1)}">
<p class="day">Вторник</p>
<p class="date">{{weekDay(1)}}</p>
</th>
<th ng-class="{current: isToday(2)}">
<p class="day">Среда</p>
<p class="date">{{weekDay(2)}}</p>
</th>
<th ng-class="{current: isToday(3)}">
<p class="day">Четверг</p>
<p class="date">{{weekDay(3)}}</p>
</th>
<th ng-class="{current: isToday(4)}">
<p class="day">Пятница</p>
<p class="date">{{weekDay(4)}}</p>
</th>
<th ng-class="{current: isToday(5)}">
<p class="day">Суббота</p>
<p class="date">{{weekDay(5)}}</p>
</th>
</tr>
</thead>
<tbody class="">
<tr ng-repeat="group in schedule">
<td class="group">
<p class="name">{{group.name}}</p>
<p class="time">{{group.time}}</p>
</td>
<td ng-repeat="day in group.days track by $index" ng-class="{current: isToday($index)}">
<p class="lesson"><a href="">{{day.lesson}}</a></p>
<p class="teacher"><a href="">{{day.teacher}}</a></p>
<p class="time">{{day.time[0]}}</p>
<p class="time">{{day.time[1]}}</p>
</td>
</tr>
</tbody>
</table>
</div>
</div>
+15
View File
@@ -0,0 +1,15 @@
<div class="head">
<div class="user">
<img ng-src="{{post.userpic}}" alt=""/>
<span>{{post.username}}</span>
</div>
<p class="date">{{post.date | date : "dd.MM.yyyy"}}</p>
</div>
<div class="body">
<!--<h2>Рисунок</h2>-->
<p>{{post.text}}</p>
<a href="{{post.url}}" target="_blank">
<img ng-src="{{post.image}}" alt="">
</a>
</div>
+9
View File
@@ -0,0 +1,9 @@
<div class="head">
<a name="{{post.uri}}"></a>
</div>
<div class="body">
<div><p class="date"><a href="#{{post.uri}}">{{post.date | date : "dd.MM.yyyy"}}</a></p></div>
<div class="message" ng-bind-html="message"></div>
</div>
+12 -18
View File
@@ -1,22 +1,16 @@
<div class="timeline">
<div class="post"
ng-repeat="post in feed"
ng-class="{left: isEven($index), right: !isEven($index)}">
<timeline-record class="timeline-record {{recordClass(post)}}"
content="post"
ng-repeat="post in feed track by $index"
ng-class="{left: isEven($index), right: !isEven($index)}">
<div class="head">
<div class="user">
<img ng-src="{{post.userpic}}" alt=""/>
<span>{{post.username}}</span>
</div>
<p class="date">{{post.date | date : "dd.MM.yyyy"}}</p>
</div>
<div class="body">
<!--<h2>Рисунок</h2>-->
<p>{{post.text}}</p>
<a href="{{post.url}}" target="_blank">
<img ng-src="{{post.image}}" alt="">
</a>
</div>
</timeline-record>
<div class="timeline-end">
<button class="more"
ng-click="loadNext()"
ng-disabled="timelineUpdating">
<span us-spinner="{radius:5, width:2, length: 4}" spinner-key="timelineMore"></span>
<span ng-hide="timelineUpdating">Ещё</span>
</button>
</div>
</div>
+17
View File
@@ -0,0 +1,17 @@
/**
* Created by tmshv on 13/03/15.
*/
var co = require("co");
var should = require("should");
var instagram = require("../instagram/instagram");
var db = require("../core/db");
var config = require("../config");
describe("Instagram", function () {
describe("getUser()", function () {
it("should return default user if exists", function () {
});
});
});
+25
View File
@@ -0,0 +1,25 @@
/**
* Created by tmshv on 08/03/15.
*/
var should = require("should");
describe("utils", function () {
describe("net.js", function () {
describe("query", function () {
var query = require("../utils/net").query;
var sample = [["count", 10], ["portion", 5], ["hello", "lol"]];
it("should combine query params", function () {
var params = query(sample);
params.should.be.equal("count=10&portion=5&hello=lol");
});
it("should return string", function () {
var params = query(sample);
params.should.be.type("string");
});
});
});
});
+15
View File
@@ -0,0 +1,15 @@
/**
* Created by tmshv on 08/03/15.
*/
module.exports = {
query: function(list){
var params = list.reduce(function (query, param) {
var q = param[0] + "=" + param[1];
query.push(q);
return query;
}, [])
.join("&");
return params
}
};