aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexander Alexeev2016-11-20 02:05:23 +0700
committerGravatar Vitaly Takmazov2016-11-23 13:03:00 +0300
commit7a2ea130863bb095fa925ec0c7576b076490f0cf (patch)
tree6289abc4383d070c39bf8528477d243a8d1dda87
parent606e2a8d6fc8af288632e2857d3a89770fdbb69c (diff)
init juick-spring-web project
-rw-r--r--juick-spring-www/build.gradle43
-rw-r--r--juick-spring-www/package.json36
-rw-r--r--juick-spring-www/src/main/webapp/WEB-INF/web.xml7
-rw-r--r--juick-spring-www/src/main/webapp/static/dialog-close.pngbin0 -> 1097 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/facebook.pngbin0 -> 203 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/favicon.pngbin0 -> 244 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/icon-fb.pngbin0 -> 203 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/icon-gplus.pngbin0 -> 501 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/icon-lj.pngbin0 -> 1183 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/icon-twitter.pngbin0 -> 458 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/icon-vk.pngbin0 -> 306 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/logo.pngbin0 -> 2447 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/logo@2x.pngbin0 -> 4822 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/menu.pngbin0 -> 479 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/photo-attachment-active.pngbin0 -> 267 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/photo-attachment.pngbin0 -> 234 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/scripts.js753
-rw-r--r--juick-spring-www/src/main/webapp/static/sharesocial.pngbin0 -> 4474 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/style.css874
-rw-r--r--juick-spring-www/src/main/webapp/static/toolbar-icons.pngbin0 -> 737 bytes
-rw-r--r--juick-spring-www/src/main/webapp/static/vk.pngbin0 -> 306 bytes
-rw-r--r--juick-spring-www/webpack.config.js37
-rw-r--r--settings.gradle3
23 files changed, 1752 insertions, 1 deletions
diff --git a/juick-spring-www/build.gradle b/juick-spring-www/build.gradle
new file mode 100644
index 00000000..2f8c0377
--- /dev/null
+++ b/juick-spring-www/build.gradle
@@ -0,0 +1,43 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ }
+}
+
+plugins {
+ id "com.moowork.node" version "0.13"
+}
+
+task compileFrontend(type: NpmTask) {
+ args = ['run', 'compile']
+}
+
+apply plugin: 'java'
+apply plugin: 'war'
+apply plugin: 'org.akhikhl.gretty'
+apply plugin: 'com.github.ben-manes.versions'
+
+def springFrameworkVersion = '4.3.4.RELEASE'
+
+dependencies {
+ compile project(':juick-server')
+ compile 'com.sun.mail:javax.mail:1.5.6'
+ compile "org.springframework:spring-webmvc:${springFrameworkVersion}"
+ providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
+ providedRuntime 'mysql:mysql-connector-java:5.1.40'
+}
+
+compileFrontend.dependsOn 'npmInstall'
+war.dependsOn 'compileFrontend'
+compileJava.options.encoding = 'UTF-8'
+
+gretty {
+ httpPort = 8080
+ contextPath = ''
+ servletContainer = 'tomcat8'
+}
+
+configurations {
+ all*.exclude module: 'commons-logging'
+}
diff --git a/juick-spring-www/package.json b/juick-spring-www/package.json
new file mode 100644
index 00000000..2eda35cd
--- /dev/null
+++ b/juick-spring-www/package.json
@@ -0,0 +1,36 @@
+{
+ "name": "juick",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "compile": "webpack --colors -p"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/juick/juick.git"
+ },
+ "license": "AGPLv3",
+ "devDependencies": {
+ "css-loader": "^0.23.1",
+ "csslint": "^1.0.2",
+ "csslint-loader": "^1.0.0",
+ "eslint": "^3.1.1",
+ "eslint-loader": "^1.4.1",
+ "extract-text-webpack-plugin": "^1.0.1",
+ "file-loader": "^0.9.0",
+ "globby": "^4.1.0",
+ "script-loader": "^0.7.0",
+ "style-loader": "^0.13.1",
+ "uglify-loader": "^1.3.0",
+ "url-loader": "^0.5.7",
+ "webpack": "^1.13.1"
+ },
+ "dependencies": {
+ "autosize": "^3.0.16",
+ "classlist.js": "^1.1.20150312",
+ "element-closest": "^2.0.1",
+ "evil-icons": "^1.8.0",
+ "whatwg-fetch": "^1.0.0"
+ }
+}
diff --git a/juick-spring-www/src/main/webapp/WEB-INF/web.xml b/juick-spring-www/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000..a57cceb9
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+
+</web-app> \ No newline at end of file
diff --git a/juick-spring-www/src/main/webapp/static/dialog-close.png b/juick-spring-www/src/main/webapp/static/dialog-close.png
new file mode 100644
index 00000000..9c4275cc
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/dialog-close.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/facebook.png b/juick-spring-www/src/main/webapp/static/facebook.png
new file mode 100644
index 00000000..5d111590
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/facebook.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/favicon.png b/juick-spring-www/src/main/webapp/static/favicon.png
new file mode 100644
index 00000000..bc7161e2
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/favicon.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/icon-fb.png b/juick-spring-www/src/main/webapp/static/icon-fb.png
new file mode 100644
index 00000000..5d111590
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/icon-fb.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/icon-gplus.png b/juick-spring-www/src/main/webapp/static/icon-gplus.png
new file mode 100644
index 00000000..d83d2520
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/icon-gplus.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/icon-lj.png b/juick-spring-www/src/main/webapp/static/icon-lj.png
new file mode 100644
index 00000000..9cde1e02
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/icon-lj.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/icon-twitter.png b/juick-spring-www/src/main/webapp/static/icon-twitter.png
new file mode 100644
index 00000000..259078f7
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/icon-twitter.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/icon-vk.png b/juick-spring-www/src/main/webapp/static/icon-vk.png
new file mode 100644
index 00000000..80b6920b
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/icon-vk.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/logo.png b/juick-spring-www/src/main/webapp/static/logo.png
new file mode 100644
index 00000000..4e0f6d56
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/logo.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/logo@2x.png b/juick-spring-www/src/main/webapp/static/logo@2x.png
new file mode 100644
index 00000000..6febeaf9
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/logo@2x.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/menu.png b/juick-spring-www/src/main/webapp/static/menu.png
new file mode 100644
index 00000000..4cac2563
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/menu.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/photo-attachment-active.png b/juick-spring-www/src/main/webapp/static/photo-attachment-active.png
new file mode 100644
index 00000000..ecbf10e8
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/photo-attachment-active.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/photo-attachment.png b/juick-spring-www/src/main/webapp/static/photo-attachment.png
new file mode 100644
index 00000000..07d48517
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/photo-attachment.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/scripts.js b/juick-spring-www/src/main/webapp/static/scripts.js
new file mode 100644
index 00000000..d368cacd
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/scripts.js
@@ -0,0 +1,753 @@
+var autosize = require('autosize');
+require('whatwg-fetch');
+require('element-closest');
+require('classlist.js');
+if (!('remove' in Element.prototype)) { // Firefox <23
+ Element.prototype.remove = function() {
+ if (this.parentNode) {
+ this.parentNode.removeChild(this);
+ }
+ };
+}
+
+NodeList.prototype.forEach = Array.prototype.forEach;
+HTMLCollection.prototype.forEach = Array.prototype.forEach;
+
+var ws,
+ pageTitle;
+
+function initWS() {
+ var content = document.getElementById('content');
+ if (!content) { return }
+ var pageMID = content.getAttribute('data-mid');
+ if (!pageMID) { return }
+
+ var url = (window.location.protocol === 'https:' ? 'wss' : 'ws') + ':'
+ + (typeof juickDebug !== 'undefined' ?
+ '//ws.juick.com/_replies' : ('//ws.juick.com/' + pageMID)),
+ hash = document.getElementById('body').getAttribute('data-hash');
+
+ if (hash) {
+ url += '?hash=' + hash;
+ }
+
+ ws = new WebSocket(url);
+ ws.onopen = function () {
+ console.log('online');
+ if (!document.querySelector('#wsthread')) {
+ var d = document.createElement('div');
+ d.id = 'wsthread';
+ d.addEventListener('click', nextReply);
+ document.querySelector('body').appendChild(d);
+ pageTitle = document.title;
+ }
+ };
+ ws.onclose = function () {
+ console.log('offline');
+ ws = false;
+ setTimeout(function () {
+ initWS();
+ }, 2000);
+ };
+ ws.onmessage = function (msg) {
+ if (msg.data == ' ') {
+ ws.send(' ');
+ } else {
+ try {
+ var jsonMsg = JSON.parse(msg.data);
+ console.log('data: ' + msg.data);
+ wsIncomingReply(jsonMsg);
+ } catch (err) {
+ console.log(err);
+ }
+ }
+ };
+ setInterval(wsSendKeepAlive, 90000);
+}
+
+function wsSendKeepAlive() {
+ if (ws) {
+ ws.send(' ');
+ }
+}
+
+function wsShutdown() {
+ if (ws) {
+ ws.onclose = function () { };
+ ws.close();
+ }
+}
+
+function isTreeMode() {
+ // relies on UserThread.printReplies implementation TODO keep this in cookie or something
+ return document.querySelector('.title2-right > a').href.match(/\?view=(\w+)/)[1] == 'list';
+}
+
+function wsIncomingReply(msg) {
+ var li = document.createElement('li');
+ li.setAttribute('class', 'msg reply-new');
+ li.setAttribute('id', msg.rid);
+ li.addEventListener('click', newReply);
+ li.addEventListener('mouseover', newReply);
+ var msgAvatar = document.createElement('div');
+ msgAvatar.setAttribute('class', 'msg-avatar');
+ var msgAvatarLink = document.createElement('a');
+ msgAvatarLink.setAttribute('href', '/' + msg.user.uname + '/');
+ var msgAvatarImg = document.createElement('img');
+ msgAvatarImg.setAttribute('src', '//i.juick.com/a/' + msg.user.uid + '.png');
+ msgAvatarLink.appendChild(msgAvatarImg);
+ msgAvatar.appendChild(msgAvatarLink);
+
+ var msgCont = document.createElement('div');
+ msgCont.setAttribute('class', 'msg-cont');
+ var msgMenu = document.createElement('div');
+ msgMenu.setAttribute('class', 'msg-menu');
+ msgCont.appendChild(msgMenu);
+ var msgMenuLink = document.createElement('a');
+ msgMenuLink.setAttribute('href', '#');
+ msgMenuLink.addEventListener('click', function (e) {
+ showMessageLinksDialog(msg.mid, msg.rid);
+ e.preventDefault();
+ });
+ msgMenu.appendChild(msgMenuLink);
+ var msgHeader = document.createElement('div');
+ msgHeader.setAttribute('class', 'msg-header');
+ var msgHeaderLink = document.createElement('a');
+ msgHeaderLink.setAttribute('href', '/' + msg.user.uname + '/');
+ msgHeaderLink.textContent = '@' + msg.user.uname + ':';
+ msgHeader.appendChild(msgHeaderLink);
+ var msgTimestamp = document.createElement('div');
+ msgTimestamp.setAttribute('class', 'msg-ts');
+ var msgTimestampLink = document.createElement('a');
+ msgTimestampLink.setAttribute('href', '/' + msg.mid + '#' + msg.rid);
+ msgTimestampLink.setAttribute('title', msg.timestamp + ' GMT');
+ msgTimestampLink.textContent = msg.timestamp;
+ msgTimestamp.appendChild(msgTimestampLink);
+ var msgTxt = document.createElement('div');
+ msgTxt.setAttribute('class', 'msg-txt');
+ var msgLinks = document.createElement('div');
+ msgLinks.setAttribute('class', 'msg-links');
+ var msgNum = '/' + msg.rid;
+ if (msg.replyto > 0) {
+ msgNum += ' в ответ на <a href="#' + msg.replyto + '">/' + msg.replyto + '</a>';
+ }
+ msgLinks.innerHTML = msgNum + ' &middot; ';
+ var msgLinksLink = document.createElement('a');
+ msgLinksLink.setAttribute('href', '#');
+ msgLinksLink.textContent = 'Ответить';
+ msgLinksLink.addEventListener('click', function (e) {
+ showCommentForm(msg.mid, msg.rid);
+ e.preventDefault();
+ });
+ msgLinks.appendChild(msgLinksLink);
+ var msgComment = document.createElement('div');
+ msgComment.setAttribute('class', 'msg-comment');
+ msgComment.style.display = 'none';
+ msgHeader.appendChild(msgAvatar);
+ msgHeader.appendChild(msgMenu);
+ msgHeader.appendChild(msgTimestamp);
+ msgCont.appendChild(msgHeader);
+ msgCont.appendChild(msgTxt);
+ msgCont.appendChild(msgLinks);
+ msgCont.appendChild(msgComment);
+ li.appendChild(msgCont);
+
+ li.querySelector('.msg-txt').textContent = msg.body;
+
+ if (isTreeMode() && (msg.replyto > 0)) {
+ var p = document.getElementById(msg.replyto);
+ var m = parseInt(p.style.marginLeft) + 20;
+ while (p.nextElementSibling && (parseInt(p.nextElementSibling.style.marginLeft) >= m)) p = p.nextElementSibling;
+ li.style.marginLeft = m + 'px';
+ p.parentNode.insertBefore(li, p.nextSibling);
+ } else {
+ document.getElementById('replies').appendChild(li);
+ }
+
+ updateRepliesCounter();
+}
+
+function newReply(e) {
+ var li = e.target;
+ li.classList.remove('reply-new');
+ li.removeEventListener('click', e);
+ li.removeEventListener('mouseover', e);
+ updateRepliesCounter();
+}
+
+function nextReply() {
+ var li = document.querySelector('#replies>li.reply-new');
+ if (li) {
+ li.classList.remove('reply-new');
+ li.removeEventListener('click', this);
+ li.childNodes[0].scrollIntoView();
+ updateRepliesCounter();
+ }
+}
+
+function updateRepliesCounter() {
+ var replies = document.querySelectorAll('#replies>li.reply-new').length;
+ var wsthread = document.getElementById('wsthread');
+ if (replies) {
+ wsthread.textContent = replies;
+ wsthread.style.display = 'block';
+ document.title = '[' + replies + '] ' + pageTitle;
+ } else {
+ wsthread.style.display = 'none';
+ document.title = pageTitle;
+ }
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******************************************************************************/
+
+function postformListener(formEl, ev) {
+ var form = formEl.closest('form');
+ if (ev.ctrlKey && (ev.keyCode == 10 || ev.keyCode == 13)) {
+ if (!form.onsubmit || form.onsubmit()) {
+ form.submit();
+ }
+ }
+}
+
+function unfoldPostForm() {
+ if (window.location.pathname === '/' && window.location.hash === '#post') {
+ document.querySelector('#newmessage>div').style.display = 'block';
+ var ta = document.querySelector('#newmessage textarea');
+ ta.style.minHeight = '70px';
+ ta.focus();
+ }
+}
+
+function newMessage() {
+ if (document.querySelector('#newmessage textarea').value.length == 0) {
+ openDialog('<p class="dialogtxt">Пожалуйста, введите текст сообщения</p>');
+ return false;
+ }
+ return true;
+}
+
+function showMoreReplies(el, id) {
+ var foldedReplies = el.closest('li').querySelector('.msg-comments');
+ if (!foldedReplies) { return }
+ foldedReplies.style.display = 'none';
+
+ var replies = document.querySelectorAll('#replies>li'),
+ flagshow = 0,
+ i = 0;
+ for (; i < replies.length; i += 1) {
+ if (flagshow == 1) {
+ if (replies[i].style.display == 'none') {
+ replies[i].style.display = 'block';
+ } else {
+ break;
+ }
+ }
+ if (replies[i].id == id) {
+ flagshow = 1;
+ }
+ }
+ return false;
+}
+
+function replyForm(mid, rid) {
+ var form = document.createElement('form');
+ form.setAttribute('action', '/comment');
+ form.setAttribute('method', 'POST');
+ form.setAttribute('enctype', 'multipart/form-data');
+ var input = document.createElement('input');
+ input.setAttribute('type', 'hidden');
+ input.setAttribute('name', 'mid');
+ input.setAttribute('value', mid);
+ form.appendChild(input);
+ if (rid) {
+ var inputRid = document.createElement('input');
+ inputRid.setAttribute('type', 'hidden');
+ inputRid.setAttribute('name', 'rid');
+ inputRid.setAttribute('value', rid);
+ form.appendChild(inputRid);
+ }
+ return form;
+}
+
+function taWrapper() {
+ var txtarea = document.createElement('textarea');
+ txtarea.setAttribute('name', 'body');
+ txtarea.setAttribute('rows', 1);
+ txtarea.setAttribute('class', 'reply narrow');
+ txtarea.setAttribute('placeholder', 'Написать комментарий...');
+ var txtKeypress = function (e) {
+ postformListener(e.target, e);
+ };
+ txtarea.addEventListener('keypress', txtKeypress);
+ var wrapper = document.createElement('div');
+ wrapper.setAttribute('class', 'ta-wrapper');
+ wrapper.appendChild(txtarea);
+ var att = document.createElement('div');
+ att.setAttribute('class', 'attach-photo');
+ att.addEventListener('click', function () {
+ attachCommentPhoto(this);
+ });
+ wrapper.appendChild(att);
+ return wrapper;
+}
+
+function showCommentForm(mid, rid) {
+ var reply = document.getElementById(rid);
+ if (reply && !reply.querySelector('textarea')) {
+ var c = reply.querySelector('div.msg-cont > .msg-comment'),
+ newNode = c.cloneNode(true),
+ form = replyForm(mid, rid);
+ form.appendChild(newNode);
+ newNode.appendChild(taWrapper());
+ var subm = document.createElement('input');
+ subm.setAttribute('type', 'submit');
+ subm.setAttribute('value', 'OK');
+ newNode.appendChild(subm);
+ c.parentNode.insertBefore(form, c);
+ c.remove();
+ }
+
+ var commentBlock = reply.querySelector('div.msg-cont > form > div.msg-comment');
+ commentBlock.style.display = 'block';
+ var commentText = commentBlock.querySelector('textarea');
+ if (commentText) {
+ autosize(commentText);
+ commentText.focus();
+ }
+}
+
+function showCommentFooter(e, mid, rid) {
+ var a = e.closest('article');
+ if (!a.querySelector('footer.comm')) {
+ var form = replyForm(mid, rid),
+ footer = document.createElement('footer');
+ footer.setAttribute('class', 'comm');
+ footer.appendChild(taWrapper());
+ var subm = document.createElement('input');
+ subm.setAttribute('type', 'submit');
+ subm.setAttribute('value', 'OK');
+ footer.appendChild(subm);
+ form.appendChild(footer);
+ a.appendChild(form);
+ autosize(a.querySelector('textarea'));
+ }
+ a.querySelector('textarea').focus();
+}
+
+function attachInput() {
+ var inp = document.createElement('input');
+ inp.setAttribute('type', 'file');
+ inp.setAttribute('name', 'attach');
+ inp.setAttribute('accept', 'image/jpeg,image/png');
+ inp.style.visibility = 'hidden';
+ return inp;
+}
+
+function attachCommentPhoto(div) {
+ if (div.children.length === 0) {
+ var inp = attachInput();
+ inp.addEventListener('change', function () {
+ inp.parentNode.classList.add('attach-photo-active');
+ });
+ inp.click();
+ div.appendChild(inp);
+ } else {
+ div.innerHTML = null;
+ div.classList.add('attach-photo');
+ }
+}
+
+function attachMessagePhoto(div) {
+ var f = div.closest('form'),
+ finput = f.querySelector('input[type="file"]');
+ if (!finput) {
+ var inp = attachInput();
+ inp.style.float = 'left';
+ inp.style.width = 0;
+ inp.style.height = 0;
+ inp.addEventListener('change', function () {
+ div.textContent = 'загрузить (✓)';
+ });
+ f.appendChild(inp);
+ inp.click();
+ } else {
+ finput.remove();
+ div.textContent = 'загрузить';
+ }
+}
+
+function unfoldReply() {
+ var anchor = window.location.hash.substring(1);
+ if ((0 + anchor) > 0) {
+ var el = document.getElementById(anchor);
+ if (!el) { return }
+ while (el.style.display === 'none') {
+ el = el.previousElementSibling;
+ }
+ showMoreReplies(el, el.getAttribute('id'));
+ window.location.replace(window.location.hash);
+ }
+}
+
+function showMessageLinksDialog(mid, rid) {
+ var hlink = window.location.protocol + '//juick.com/' + mid,
+ mlink = '#' + mid;
+ if (rid > 0) {
+ hlink += '#' + rid;
+ mlink += '/' + rid;
+ }
+ var hlinkenc = encodeURIComponent(hlink),
+ html = '<div class="dialogshare">Ссылка на сообщение:'
+ + '<div onclick="this.selectText()" class="dialogl">' + hlink + '</div>'
+ + 'Номер сообщения:'
+ + '<div onclick="this.selectText()" class="dialogl">' + mlink + '</div>'
+ + 'Поделиться:<ul>'
+ + '<li><a href="https://www.facebook.com/sharer/sharer.php?u=' + hlinkenc + '" onclick="return openSocialWindow(this)"></a></li>'
+ + '<li><a href="https://twitter.com/intent/tweet?url=' + hlinkenc + '" onclick="return openSocialWindow(this)" style="background-position: -32px 0;"></a></li>'
+ + '<li><a href="https://vk.com/share.php?url=' + hlinkenc + '" onclick="return openSocialWindow(this)" style="background-position: -64px 0;"></a></li>'
+ + '<li><a href="https://plus.google.com/share?url=' + hlinkenc + '" onclick="return openSocialWindow(this)" style="background-position: -96px 0;"></a></li>'
+ + '</ul></div>';
+
+ openDialog(html);
+}
+
+function showPhotoDialog(fname) {
+ var width = window.innerWidth,
+ height = window.innerHeight * 0.9;
+ if (width < 640) {
+ return true;
+ } else if (width < 1280) {
+ openDialog('<a href="//i.juick.com/photos-1024/' + fname + '"><img src="//i.juick.com/photos-512/' + fname + '"/></a>');
+ document.querySelector('#dialogw img').style.maxHeight = height + 'px';
+ return false;
+ } else {
+ openDialog('<a href="//i.juick.com/p/' + fname + '"><img src="//i.juick.com/photos-1024/' + fname + '"/></a>');
+ document.querySelector('#dialogw img').style.maxHeight = height + 'px';
+ return false;
+ }
+}
+
+function openDialog(html) {
+ var dhtml = '<table id="dialogt"><tr><td><div id="dialogb"></div><div id="dialogw"><div id="dialogc"></div>' + html + '</div></td></tr></table>';
+ document.querySelector('body').insertAdjacentHTML('afterbegin', dhtml);
+ document.querySelector('#dialogb').addEventListener('click', closeDialog);
+ document.querySelector('#dialogc').addEventListener('click', closeDialog);
+}
+
+function closeDialog() {
+ document.querySelector('#dialogb').remove();
+ document.querySelector('#dialogt').remove();
+}
+
+function openSocialWindow(a) {
+ var w = window.open(a.href, 'juickshare', 'width=640,height=400');
+ if (window.focus) w.focus();
+ return false;
+}
+
+function checkUsername() {
+ var uname = document.querySelector('#username').textContent,
+ style = document.querySelector('#username').style;
+ fetch('//api.juick.com/users?uname=' + uname)
+ .then(function () {
+ style.background = '#FFCCCC';
+ })
+ .catch(function () {
+ style.background = '#CCFFCC';
+ });
+}
+
+/******************************************************************************/
+
+function openDialogLogin() {
+ var html = '<div class="dialoglogin"><p>Пожалуйста, представьтесь:'
+ + '<a href="/_fblogin" id="signfb">Facebook</a> '
+ + '<a href="/_vklogin" id="signvk">ВКонтакте</a></p>'
+ + '<p>Уже зарегистрированы?</p>'
+ + '<form action="/login" method="POST">'
+ + '<input class="signinput" type="text" name="username" placeholder="Имя пользователя"/><br/>'
+ + '<input class="signinput" type="password" name="password" placeholder="Пароль"/><br/>'
+ + '<input class="signsubmit" type="submit" value="OK"/>'
+ + '</form></div>';
+ openDialog(html);
+ return false;
+}
+
+/******************************************************************************/
+
+function resultMessage(str) {
+ var result = document.createElement('p');
+ result.textContent = str;
+ return result;
+}
+
+function likeMessage(e, mid) {
+ if (confirm('Are you sure?')) {
+ fetch('//juick.com/like?mid=' + mid, {
+ method: 'POST',
+ credentials: 'same-origin'
+ })
+ .then(function (response) {
+ if (response.ok) {
+ e.closest('article').appendChild(resultMessage('OK!'));
+ }
+ })
+ .catch(function () {
+ e.closest('article').appendChild(resultMessage('Ошибка'));
+ });
+ }
+ return false;
+}
+
+/******************************************************************************/
+
+function setPopular(e, mid, popular) {
+ fetch('//api.juick.com/messages/set_popular?mid=' + mid
+ + '&popular=' + popular
+ + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
+ credentials: 'same-origin'
+ })
+ .then(function () {
+ e.closest('article').append(resultMessage('OK!'));
+ });
+ return false;
+}
+
+function setPrivacy(e, mid) {
+ fetch('//api.juick.com/messages/set_privacy?mid=' + mid
+ + '&hash=' + document.getElementById('body').getAttribute('data-hash'), {
+ credentials: 'same-origin'
+ })
+ .then(function () {
+ e.closest('article').append(resultMessage('OK!'));
+ });
+ return false;
+}
+/******************************************************************************/
+
+Element.prototype.selectText = function () {
+ var d = document;
+ if (d.body.createTextRange) {
+ var range = d.body.createTextRange();
+ range.moveToElementText(this);
+ range.select();
+ } else if (window.getSelection) {
+ var selection = window.getSelection();
+ var rangeSel = d.createRange();
+ rangeSel.selectNodeContents(this);
+ selection.removeAllRanges();
+ selection.addRange(rangeSel);
+ }
+};
+
+function ready(fn) {
+ if (document.readyState != 'loading') {
+ fn();
+ } else {
+ document.addEventListener('DOMContentLoaded', fn);
+ }
+}
+
+ready(function () {
+ autosize(document.querySelectorAll('textarea'));
+
+ var insertButtons = function (e) {
+ var textarea = e.target;
+ textarea.classList.add('narrow');
+ var att = document.createElement('div');
+ att.classList.add('attach-photo');
+ att.addEventListener('click', function(e) {
+ attachCommentPhoto(e.target);
+ });
+ textarea.parentNode.insertBefore(att, textarea.nextSibling);
+ textarea.parentNode.insertAdjacentHTML('afterend', '<input type="submit" value="OK"/>');
+ textarea.removeEventListener('click', insertButtons);
+ e.preventDefault();
+ };
+ document.querySelectorAll('textarea.reply').forEach(function(e) {
+ e.addEventListener('click', insertButtons);
+ e.addEventListener('keypress', function(e) {
+ postformListener(e.target, e);
+ });
+ });
+
+ var insertPMButtons = function (e) {
+ e.target.classList.add('narrowpm');
+ e.target.parentNode.insertAdjacentHTML('afterend', '<input type="submit" value="OK"/>');
+ e.target.removeEventListener('click', insertPMButtons);
+ e.preventDefault();
+ };
+ document.querySelectorAll('textarea.replypm').forEach(function(e) {
+ e.addEventListener('click', insertPMButtons);
+ });
+
+ var content = document.getElementById('content');
+ if (content) {
+ var pageMID = content.getAttribute('data-mid');
+ if (pageMID > 0) {
+ document.querySelectorAll('.msg-comments').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ var rid = e.target.closest('li').id;
+ showMoreReplies(e.target, rid);
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.a-thread-comment').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ var rid = e.target.closest('li').id;
+ showCommentForm(pageMID, rid);
+ e.preventDefault();
+ });
+ });
+ }
+ }
+
+ document.querySelectorAll('.msg-menu a').forEach(function(el) {
+ el.addEventListener('click', function(e) {
+ showMessageLinksDialog(
+ e.target.closest('section').getAttribute('data-mid'),
+ parseInt(e.target.closest('li').id)); // rid
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.l .a-comment').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ showCommentFooter(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'));
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.l .a-privacy').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ setPrivacy(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'));
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.l .a-popular-plus').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ setPopular(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'),
+ 2);
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.l .a-popular-minus').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ setPopular(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'),
+ -1);
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.l .a-popular-delete').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ setPopular(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'),
+ -2);
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.ir a').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ var fname = e.target.closest('[data-fname]').getAttribute('data-fname');
+ if (!showPhotoDialog(fname)) {
+ e.preventDefault();
+ }
+ });
+ });
+ document.querySelectorAll('.social a').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ openSocialWindow(e.target);
+ e.preventDefault();
+ });
+ });
+ var username = document.getElementById('username');
+ if (username) {
+ username.addEventListener('blur', function () {
+ checkUsername();
+ });
+ }
+
+ document.querySelectorAll('.l .a-like').forEach(function(e) {
+ e.addEventListener('click', function (e) {
+ likeMessage(
+ e.target,
+ e.target.closest('article').getAttribute('data-mid'));
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.a-login').forEach(function(el) {
+ el.addEventListener('click', function(e) {
+ openDialogLogin();
+ e.preventDefault();
+ });
+ });
+ document.querySelectorAll('.attach-photo').forEach(function(el) {
+ el.addEventListener('click', function(e) {
+ attachCommentPhoto(e.target);
+ });
+ });
+ var unfoldall = document.getElementById('unfoldall');
+ if (unfoldall) {
+ unfoldall.addEventListener('click', function(e) {
+ document.querySelectorAll('#replies>li').forEach(function(e) {
+ e.style.display = 'block';
+ });
+ document.querySelectorAll('#replies .msg-comments').forEach(function(e) {
+ e.style.display = 'none';
+ });
+ e.preventDefault();
+ });
+ }
+ var newMessageBlock = document.getElementById('newmessage');
+ if (newMessageBlock) {
+ var form = newMessageBlock.parentNode;
+ form.addEventListener('submit', newMessage);
+ newMessageBlock.querySelector('textarea').addEventListener('click', function(e) {
+ var parent = e.target.parentNode;
+ parent.querySelector('div').style.display = 'block';
+ e.target.style.minHeight = '70px';
+ e.target.addEventListener('keypress', function(e) {
+ postformListener(e.target, e);
+ });
+ });
+ newMessageBlock.querySelector('a').addEventListener('click', function(e) {
+ attachMessagePhoto(e.target);
+ });
+ }
+ document.querySelectorAll('article').forEach(function(article) {
+ if (Array.prototype.some.call(
+ article.querySelectorAll('.u a'),
+ function (a) {
+ return a.textContent === 'NSFW';
+ }
+ )) {
+ var img = article.querySelector('.ir img');
+ if (img) {
+ img.style.opacity = 0.05;
+ img.addEventListener('mouseover', function(e) {
+ e.target.style.opacity = 1;
+ });
+ img.addEventListener('mouseout', function(e) {
+ e.target.style.opacity = 0.05;
+ });
+ }
+ }
+ });
+
+ unfoldPostForm();
+ unfoldReply();
+ initWS();
+ window.addEventListener('hashchange', unfoldPostForm);
+ window.addEventListener('hashchange', unfoldReply);
+
+ window.addEventListener('pagehide', wsShutdown);
+});
diff --git a/juick-spring-www/src/main/webapp/static/sharesocial.png b/juick-spring-www/src/main/webapp/static/sharesocial.png
new file mode 100644
index 00000000..1031b343
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/sharesocial.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/style.css b/juick-spring-www/src/main/webapp/static/style.css
new file mode 100644
index 00000000..46af7b81
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/style.css
@@ -0,0 +1,874 @@
+html,body,div,h1,h2,ul,li,p,form,input,textarea,pre {
+ margin: 0;
+ padding: 0;
+}
+html,input,textarea {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Droid Sans", "Helvetica Neue", sans-serif;
+ font-size: 12pt;
+ -webkit-font-smoothing: subpixel-antialiased;
+}
+html {
+ background: #EEEEE5;
+ color: #222;
+}
+body {
+ margin: 0 auto;
+ width: 1000px;
+}
+h1,h2 {
+ font-weight: normal;
+}
+ul {
+ list-style-type: none;
+}
+a {
+ color: #069;
+ text-decoration: none;
+}
+img,hr {
+ border: none;
+}
+hr {
+ background: #CCC;
+ height: 1px;
+ margin: 10px 0;
+}
+pre {
+ white-space: pre-wrap;
+ white-space: -moz-pre-wrap;
+ white-space: -pre-wrap;
+ white-space: -o-pre-wrap;
+ word-wrap: break-word;
+}
+span.u {
+ text-decoration: underline;
+}
+#content {
+ float: right;
+ margin: 25px 0 0 0;
+ width: 728px;
+}
+#topwrapper {
+ clear: both;
+ position: relative;
+}
+body>header {
+ width: 1000px;
+}
+body>header a {
+ border-bottom: 1px dotted #666;
+ color: #222;
+ font-size: 13pt;
+}
+#logo {
+ float: left;
+ height: 36px;
+ margin: 7px 25px 0 20px;
+ width: 110px;
+}
+#logo a {
+ background: url("logo.png") no-repeat;
+ border: 0;
+ display: block;
+ height: 36px;
+ overflow: hidden;
+ text-indent: 100%;
+ white-space: nowrap;
+ width: 110px;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 2),(min-resolution: 192dpi) {
+ #logo a {
+ background: url("logo@2x.png") no-repeat;
+ background-size: cover;
+ }
+}
+nav#global {
+ float: left;
+}
+nav#global li {
+ display: inline-block;
+ margin: 14px 12px 0 0;
+}
+#search {
+ float: right;
+ margin: 12px 20px 12px 0;
+}
+#search input {
+ background: #FFF;
+ border: 1px solid #DDDDD5;
+ padding: 4px;
+}
+#headdiv {
+ background: #DDDDD5;
+ border-bottom: 1px solid #D5D5D0;
+ border-top: 1px solid #D5D5D0;
+ clear: both;
+ margin: 0 0 5px 0;
+ padding: 0 20px;
+ position: relative;
+}
+#headdiv li {
+ display: inline-block;
+ margin: 12px 12px 12px 0;
+}
+nav#actions {
+ position: absolute;
+ right: 8px;
+ top: 0;
+}
+body>header nav li:after {
+ color: #AAA;
+ content: "/";
+ display: inline-block;
+ margin-left: 12px;
+}
+body>header nav li:last-child:after {
+ display: none;
+}
+body>header p {
+ color: #222;
+ font-size: 13pt;
+ margin: 12px 0;
+ text-align: center;
+}
+#content>p, #content>h1, #content>h2 {
+ margin: 1em 0;
+}
+#newmessage {
+ background: #E5E5E0;
+ margin-bottom: 20px;
+ padding: 15px;
+}
+#newmessage textarea {
+ border: 1px solid #CCC;
+ height: 14pt;
+ margin: 0 0 5px 0;
+ min-height: 14pt;
+ padding: 4px;
+ resize: vertical;
+ width: 688px;
+}
+#newmessage input {
+ border: 1px solid #CCC;
+ margin: 5px 0;
+ padding: 2px 4px;
+}
+#newmessage>div {
+ display: none;
+}
+#newmessage .img {
+ width: 500px;
+}
+#newmessage .tags {
+ width: 500px;
+}
+#newmessage .subm {
+ background: #EEEEE5;
+ width: 150px;
+}
+article {
+ background: #fff;
+ line-height: 140%;
+ margin-bottom: 20px;
+ padding: 20px;
+}
+article aside {
+ float: left;
+ height: 48px;
+ margin-right: 10px;
+ width: 48px;
+}
+article aside img {
+ height: 48px;
+ width: 48px;
+}
+article time {
+ border-bottom: 1px dotted #999;
+ color: #999;
+ font-size: 10pt;
+}
+article p {
+ clear: left;
+ margin: 5px 0 15px 0;
+}
+article p.i {
+ text-align: center;
+}
+article p.ir {
+ float: right;
+ margin-bottom: 10px;
+ margin-left: 10px;
+}
+article p.ir a {
+ cursor: -moz-zoom-in;
+ cursor: -webkit-zoom-in;
+}
+article p.ir img {
+ max-height: 200px;
+ max-width: 200px;
+}
+article .irbr {
+ clear: right;
+}
+article>nav.l {
+ display: inline-block;
+ font-size: 10pt;
+}
+article>nav.l a {
+ border-bottom: 1px dotted #AAA;
+ color: #888;
+ margin-right: 15px;
+}
+article>nav.s {
+ display: inline-block;
+ float: right;
+ text-align: right;
+}
+article>nav.s a {
+ color: #222;
+ font-weight: bold;
+ vertical-align: middle;
+}
+article a.likes {
+ padding-left: 20px;
+}
+article a.replies {
+ margin-left: 18px;
+}
+article footer.comm {
+ margin: 13px 0 0 0;
+}
+article textarea {
+ border: 0;
+ height: 12pt;
+ min-height: 12pt;
+ padding: 2px;
+ resize: vertical;
+ vertical-align: top;
+ width: 530px;
+}
+article input {
+ background: #EEE;
+ border: 1px solid #CCC;
+ color: #999;
+ margin-left: 6px;
+ min-width: 50px;
+ vertical-align: top;
+}
+article .tags {
+ margin-top: 3px;
+}
+.msg-tags {
+ margin-top: 5px;
+}
+article .tags>a, .msg-tags>a {
+ border: 1px dotted #ccc;
+ color: #888;
+ display: inline-block;
+ font-size: 10pt;
+ margin-bottom: 5px;
+ margin-right: 5px;
+ padding: 0 10px;
+}
+#geomap {
+ height: 300px;
+ margin-top: 1em;
+ overflow: hidden;
+ width: 700px;
+}
+.msg {
+ margin: 10px 0 20px 0;
+}
+.ads {
+ background: #FFF;
+ margin: 8px 0 16px 58px;
+ padding: 13px 10px 5px 10px;
+}
+.msgthread {
+ margin-bottom: 0;
+}
+.msg-avatar {
+ float: left;
+ height: 48px;
+ margin-right: 10px;
+ width: 48px;
+}
+.msg-avatar img {
+ height: 48px;
+ vertical-align: top;
+ width: 48px;
+}
+.msg-cont {
+ background: #FFF;
+ line-height: 140%;
+ margin-bottom: 20px;
+ padding: 20px;
+ width: 640px;
+}
+.msg-menu {
+ float: right;
+ height: 16px;
+ margin-left: 10px;
+ margin-top: 2.4px;
+ width: 16px;
+}
+.msg-menu>a {
+ background: url("menu.png") no-repeat;
+ display: block;
+ height: 16px;
+ vertical-align: top;
+ width: 16px;
+}
+.msg-ts, article header.t {
+ float: right;
+ font-size: small;
+ vertical-align: top;
+}
+.msg-ts, .msg-ts>a {
+ color: #999;
+}
+.msg-place {
+ font-size: small;
+}
+.msg-place>a {
+ color: #999;
+}
+.msg-txt {
+ clear: both;
+ margin: 0 0 12px;
+ padding-top: 10px;
+}
+.msg-media {
+ text-align: center;
+}
+.msg-links {
+ color: #999;
+ font-size: small;
+ margin: 5px 0 0 0;
+}
+.msg-comments {
+ color: #AAA;
+ font-size: small;
+ margin-top: 10px;
+ overflow: hidden;
+ text-indent: 10px;
+}
+.ta-wrapper {
+ border: 1px solid #DDD;
+ display: inline-block;
+}
+.msg-comment textarea {
+ border: 0;
+ height: 12pt;
+ min-height: 12pt;
+ padding: 2px;
+ resize: vertical;
+ vertical-align: top;
+ width: 634px;
+}
+.msg-comment .narrow {
+ width: 554px;
+}
+.msg-comment .narrowpm {
+ width: 580px;
+}
+.attach-photo {
+ background: url("photo-attachment.png") no-repeat 3px 4px;
+ cursor: pointer;
+ display: inline-block;
+ height: 13px;
+ overflow: hidden;
+ padding: 2px 4px;
+ width: 16px;
+}
+.attach-photo-active {
+ background: url("photo-attachment-active.png") no-repeat 3px 4px;
+ cursor: pointer;
+ display: inline-block;
+ height: 13px;
+ overflow: hidden;
+ padding: 2px 4px;
+ width: 16px;
+}
+.msg-comment input {
+ background: #EEE;
+ border: 1px solid #CCC;
+ color: #999;
+ margin-left: 6px;
+ vertical-align: top;
+ width: 50px;
+}
+.msg-recomms {
+ color: #AAA;
+ font-size: small;
+ margin-top: 10px;
+ overflow: hidden;
+ text-indent: 10px;
+}
+.reply-new .msg-cont {
+ border-right: 5px solid #0C0;
+}
+q:before, q:after {
+ content: "";
+}
+q {
+ border-left: 1px dashed #CCC;
+ color: #666;
+ display: block;
+ margin: 10px 0 10px 10px;
+ padding-left: 10px;
+}
+#mtoolbar {
+ background: #E5E5DD;
+ border-top: 1px solid #CCC;
+ width: 680px;
+}
+#mtoolbar ul, #mtoolbar a {
+ padding: 5px;
+}
+#mtoolbar li {
+ display: inline;
+}
+#mtoolbar div {
+ background: url("toolbar-icons.png") no-repeat;
+ display: inline-block;
+ height: 16px;
+ margin: 5px;
+ vertical-align: middle;
+ width: 16px;
+}
+#replies .msg-txt, #private-messages .msg-txt {
+ margin: 0;
+}
+.msg-comment {
+ margin-top: 10px;
+}
+.newmessage {
+ border: 1px solid #DDD;
+ padding: 2px;
+ resize: vertical;
+ width: 695px;
+}
+.users {
+ margin: 10px 0;
+ width: 100%;
+}
+.users td {
+ overflow: hidden;
+ padding: 6px 0;
+ width: 33%;
+}
+.users img {
+ height: 32px;
+ margin-right: 6px;
+ vertical-align: middle;
+ width: 32px;
+}
+.title2 {
+ background: #DDDDD0;
+ margin: 20px 0;
+ padding: 10px 20px;
+}
+.title2-right {
+ float: right;
+ line-height: 24px;
+}
+#content .title2 h2 {
+ font-size: x-large;
+ margin: 0;
+}
+.page {
+ background: #E5E5DD;
+ padding: 5px;
+ text-align: center;
+}
+.signup-h1>img {
+ margin-right: 10px;
+ vertical-align: middle;
+}
+.signup-h1 {
+ font-size: x-large;
+ margin: 20px 0 10px 0;
+}
+.signup-h2 {
+ font-size: large;
+ margin: 10px 0 5px 0;
+}
+.signup-hr {
+ margin: 20px 0;
+}
+.newpm {
+ margin: 20px 60px 30px 60px;
+}
+.newpm textarea {
+ resize: vertical;
+ width: 100%;
+}
+.newpm-send input {
+ width: 100px;
+}
+#column {
+ float: left;
+ margin-left: 10px;
+ overflow: hidden;
+ padding-top: 10px;
+ width: 240px;
+}
+#column ul, #column p, #column hr {
+ margin: 10px 0;
+}
+#column li {
+ margin: 6px 0;
+}
+#column .margtop {
+ margin-top: 15px;
+}
+#column p {
+ font-size: 10pt;
+ line-height: 140%;
+}
+#column .tags {
+ text-align: justify;
+}
+#column .inp {
+ background: #F5F5E9;
+ border: 1px solid #CCC;
+ border-radius: 3px;
+ padding: 3px;
+ width: 222px;
+}
+#ctitle {
+ font-size: 14pt;
+}
+#ctitle img {
+ margin-right: 5px;
+ vertical-align: middle;
+}
+#ctoolbar {
+ background: #E5E5DD;
+ line-height: 0;
+ margin: 10px 0;
+ padding: 5px;
+}
+#ctoolbar li {
+ display: inline;
+}
+#ctoolbar a {
+ padding: 5px 10px;
+}
+#ctoolbar div {
+ background: url("toolbar-icons.png") no-repeat;
+ display: inline-block;
+ height: 16px;
+ margin: 5px 0;
+ vertical-align: middle;
+ width: 16px;
+}
+#ustats li {
+ font-size: 10pt;
+ margin: 3px 0;
+}
+#column table.iread {
+ width: 100%;
+}
+#column table.iread td {
+ text-align: center;
+}
+#column table.iread img {
+ height: 48px;
+ width: 48px;
+}
+#dialogb {
+ background: #222;
+ height: 100%;
+ left: 0;
+ opacity: 0.6;
+ position: fixed;
+ top: 0;
+ width: 100%;
+ z-index: 10;
+}
+#dialogt {
+ height: 100%;
+ left: 0;
+ position: fixed;
+ top: 0;
+ width: 100%;
+ z-index: 10;
+}
+#dialogt td {
+ text-align: center;
+ vertical-align: middle;
+}
+#dialogw {
+ display: inline-block;
+ position: relative;
+ text-align: left;
+ z-index: 11;
+}
+#dialogc {
+ background: url("dialog-close.png");
+ cursor: pointer;
+ height: 30px;
+ position: absolute;
+ right: -15px;
+ top: -15px;
+ width: 30px;
+ z-index: 12;
+}
+.dialoglogin {
+ background: #EEEEE5;
+ padding: 25px;
+ width: 300px;
+}
+#signfb,#signvk {
+ display: block;
+ height: 32px;
+ line-height: 32px;
+ margin: 10px 0;
+ overflow: hidden;
+ text-decoration: none;
+ text-indent: 37px;
+ width: 100%;
+}
+#signfb {
+ background: url("facebook.png") no-repeat #3A569C;
+ color: #FFF;
+}
+#signvk {
+ background: url("vk.png") no-repeat #6d8fb3;
+ color: #FFF;
+ margin-bottom: 30px;
+}
+.dialoglogin form {
+ margin-top: 7px;
+}
+.signinput,.signsubmit {
+ border: 1px solid #CCC;
+ margin: 3px 0;
+ padding: 3px;
+}
+.signinput {
+ width: 292px;
+}
+.signsubmit {
+ width: 70px;
+}
+.dialogshare {
+ background: #EEEEE5;
+ border: 1px solid #999;
+ min-width: 300px;
+ overflow: auto;
+ padding: 20px;
+}
+.dialogl {
+ background: #F5F5E9;
+ border: 1px solid #DDD;
+ margin: 3px 0 20px;
+ padding: 5px;
+}
+.dialogshare li {
+ float: left;
+ margin: 5px 10px 0 0;
+}
+.dialogshare a {
+ background-image: url("sharesocial.png");
+ display: block;
+ height: 32px;
+ width: 32px;
+}
+.dialogtxt {
+ background: #EEEEE5;
+ padding: 20px;
+}
+#wsthread {
+ background: #CCC;
+ bottom: 20px;
+ cursor: pointer;
+ display: none;
+ padding: 5px 10px;
+ position: fixed;
+ right: 20px;
+}
+#footer {
+ clear: both;
+ color: #999;
+ font-size: 10pt;
+ margin: 0 auto 20px 0;
+ padding: 10px 0;
+ width: 1004px;
+}
+#footer-social {
+ float: left;
+}
+#footer-social a {
+ border: 0;
+ display: inline-block;
+ height: 32px;
+ margin: 0 15px 0 0;
+ overflow: hidden;
+ text-indent: 100%;
+ white-space: nowrap;
+ width: 32px;
+}
+#footer-left {
+ margin-left: 286px;
+ margin-right: 350px;
+}
+#footer-right {
+ float: right;
+}
+.sharenew {
+ color: #FFF;
+ display: inline-block;
+ line-height: 32px;
+ min-height: 32px;
+ min-width: 200px;
+ padding: 0 12px 0 37px;
+}
+.ico32-twi {
+ background: #55acee url("icon-twitter.png") no-repeat;
+}
+.ico32-vk {
+ background: #6d8fb3 url("icon-vk.png") no-repeat;
+}
+.ico32-fb {
+ background: #3b579d url("icon-fb.png") no-repeat;
+}
+.ico32-lj {
+ background: #888888 url("icon-lj.png") no-repeat;
+}
+.ico32-gp {
+ background: #dc4a38 url("icon-gplus.png") no-repeat;
+}
+.icon {
+ margin-top: -2px;
+ vertical-align: middle;
+}
+.icon--ei-comment {
+ margin-top: -3px;
+}
+fieldset {
+ border: 1px dotted #ccc;
+ margin-top: 25px;
+}
+@media screen and (max-width: 850px) {
+ body {
+ text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+ }
+ body,body>header,#topwrapper,#content,#footer,#mtoolbar {
+ float: none;
+ margin: 0 auto;
+ min-width: 310px;
+ width: auto;
+ }
+ body>header {
+ margin-bottom: 15px;
+ }
+ body>header a {
+ font-size: 12pt;
+ }
+ #logo {
+ display: none;
+ }
+ nav#global {
+ margin-left: 10px;
+ }
+ nav#global li {
+ margin-right: 10px;
+ }
+ #search {
+ display: inline-block;
+ float: none;
+ margin: 10px 10px;
+ }
+ #headdiv {
+ padding: 0 10px;
+ }
+ #headdiv li {
+ margin-right: 10px;
+ }
+ nav#actions {
+ position: relative;
+ right: auto;
+ }
+ #newmessage .img, #newmessage .tags {
+ width: 100%;
+ }
+ #column {
+ float: none;
+ margin: 0 10px;
+ padding-top: 0;
+ width: auto;
+
+ }
+ article {
+ margin: 8px;
+ overflow: auto;
+ }
+ article p {
+ margin: 10px 0 8px 0;
+ }
+ article>nav.l {
+ display: block;
+ float: left;
+ line-height: 15pt;
+ width: 80%;
+ }
+ article>nav.s {
+ display: block;
+ }
+ article textarea {
+ width: 205px;
+ }
+ article footer {
+ float: left;
+ }
+ #content textarea {
+ width: 100%;
+ }
+ .msg,.msg-cont {
+ min-width: 280px;
+ width: auto;
+ }
+ .msg-cont,.ads {
+ margin: 8px;
+ }
+ .msg-comment textarea {
+ width: 100%;
+ }
+ .msg-media {
+ overflow: auto;
+ }
+ .title2 h2 {
+ font-size: large;
+ }
+ #footer {
+ margin: 0 10px;
+ }
+ #footer div {
+ float: none;
+ margin: 10px 0;
+ }
+}
+@media screen and (max-width: 480px) {
+ .msg-ts {
+ float: none;
+ }
+ .msg-tags {
+ margin-top: 10px;
+ }
+ .msg-txt {
+ padding-top: 5px;
+ }
+ .title2 {
+ font-size: 11pt;
+ }
+ #content .title2 h2 {
+ font-size: 11pt;
+ }
+ .title2-right {
+ line-height: initial;
+ }
+}
diff --git a/juick-spring-www/src/main/webapp/static/toolbar-icons.png b/juick-spring-www/src/main/webapp/static/toolbar-icons.png
new file mode 100644
index 00000000..cd4efd45
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/toolbar-icons.png
Binary files differ
diff --git a/juick-spring-www/src/main/webapp/static/vk.png b/juick-spring-www/src/main/webapp/static/vk.png
new file mode 100644
index 00000000..80b6920b
--- /dev/null
+++ b/juick-spring-www/src/main/webapp/static/vk.png
Binary files differ
diff --git a/juick-spring-www/webpack.config.js b/juick-spring-www/webpack.config.js
new file mode 100644
index 00000000..acefc658
--- /dev/null
+++ b/juick-spring-www/webpack.config.js
@@ -0,0 +1,37 @@
+var webpack = require("webpack")
+var globby = require("globby")
+var ExtractTextPlugin = require("extract-text-webpack-plugin")
+module.exports = {
+ devtool: 'source-map',
+ entry: {
+ "scripts" : globby.sync([
+ __dirname + "/src/main/webapp/static/*.*",
+ require.resolve('evil-icons/assets/evil-icons.css'),
+ require.resolve('evil-icons/assets/evil-icons.js')
+ ])
+ },
+ output: {
+ path: __dirname + "/src/main/webapp",
+ filename: "[name].js"
+ },
+ module: {
+ preLoaders: [
+ { test: /\.jsx?$/, loader: 'eslint', exclude: /node_modules/ },
+ { test: /\.css$/, loader: 'csslint?failOnWarning=false', exclude: /node_modules/ }
+ ],
+ loaders: [
+ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") },
+ { test: /\.png$/, loader: "url-loader?limit=10000000000" },
+ { test: /\.svg$/, loader: "url-loader?limit=10000000000" }
+ ]
+ },
+ plugins: [
+ new ExtractTextPlugin("style.css", {
+ allChunks: true
+ })
+ ],
+ eslint: {
+ failOnWarning: false,
+ failOnError: true
+ },
+} \ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index 1edde226..773e9537 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,2 @@
-include ':juick-core', 'juick-server', ':juick-api', ':juick-www', ':juick-rss', ':juick-ws', ':juick-demo', ':juick-notifications', ':juick-crosspost', ':juick-xmpp', ':juick-xmpp-ft', ':juick-xmpp-bot'
+include ':juick-core', 'juick-server', ':juick-api', ':juick-www', ':juick-rss', ':juick-ws', ':juick-demo', ':juick-notifications', ':juick-crosspost', ':juick-xmpp', ':juick-xmpp-ft', ':juick-xmpp-bot', ':juick-spring-www'
+