diff options
15 files changed, 346 insertions, 82 deletions
diff --git a/juick-server/src/main/java/com/juick/service/CrosspostService.java b/juick-server/src/main/java/com/juick/service/CrosspostService.java index 88821b60..725ef297 100644 --- a/juick-server/src/main/java/com/juick/service/CrosspostService.java +++ b/juick-server/src/main/java/com/juick/service/CrosspostService.java @@ -12,13 +12,21 @@ public interface CrosspostService { Optional<Pair<String, String>> getTwitterTokens(int uid); + boolean deleteTwitterToken(Integer uid); + Optional<String> getFacebookToken(int uid); ApplicationStatus getFbCrossPostStatus(int uid); + boolean enableFBCrosspost(Integer uid); + + void disableFBCrosspost(Integer uid); + String getTwitterName(int uid); String getTelegramName(int uid); Optional<Pair<String, String>> getVkTokens(int uid); + + void deleteVKUser(Integer uid); } diff --git a/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java b/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java index ed1cd676..0f043292 100644 --- a/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/CrosspostServiceImpl.java @@ -14,7 +14,6 @@ import java.util.Optional; * Created by aalexeev on 11/13/16. */ @Repository -@Transactional(readOnly = true) public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostService { @Inject @@ -22,6 +21,7 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe super(jdbcTemplate, null); } + @Transactional(readOnly = true) @Override public Optional<Pair<String, String>> getTwitterTokens(final int uid) { List<Optional<Pair<String, String>>> list = getJdbcTemplate().query( @@ -33,6 +33,14 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe Optional.empty() : list.get(0); } + @Transactional + @Override + public boolean deleteTwitterToken(Integer uid) { + return getJdbcTemplate().update("DELETE FROM twitter WHERE user_id=?", uid) > 0 + && getJdbcTemplate().update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=1741", uid) > 0; + } + + @Transactional(readOnly = true) @Override public Optional<String> getFacebookToken(final int uid) { List<String> list = getJdbcTemplate().queryForList( @@ -43,6 +51,7 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe Optional.empty() : Optional.of(list.get(0)); } + @Transactional(readOnly = true) @Override public ApplicationStatus getFbCrossPostStatus(final int uid) { List<ApplicationStatus> list = getJdbcTemplate().query( @@ -61,6 +70,24 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe new ApplicationStatus() : list.get(0); } + @Transactional + @Override + public boolean enableFBCrosspost(Integer uid) { + return getJdbcTemplate().update("UPDATE facebook SET crosspost=1 WHERE user_id=?", uid) > 0 + && getJdbcTemplate().update( + "INSERT INTO subscr_users(user_id,suser_id,jid,active) VALUES (?,5863,'juick@facebook.juick.com',1)", + uid) > 0; + } + + @Transactional + @Override + public void disableFBCrosspost(Integer uid) { + getJdbcTemplate().update("UPDATE facebook SET crosspost=0 WHERE user_id=?", uid); + // TODO: stop using magic numbers for system users + getJdbcTemplate().update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=5863", uid); + } + + @Transactional(readOnly = true) @Override public String getTwitterName(final int uid) { List<String> list = getJdbcTemplate().queryForList( @@ -72,6 +99,7 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe "" : list.get(0); } + @Transactional(readOnly = true) @Override public String getTelegramName(final int uid) { List<String> list = getJdbcTemplate().queryForList( @@ -83,6 +111,7 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe "" : list.get(0); } + @Transactional(readOnly = true) @Override public Optional<Pair<String, String>> getVkTokens(final int uid) { List<Optional<Pair<String, String>>> list = getJdbcTemplate().query( @@ -93,4 +122,10 @@ public class CrosspostServiceImpl extends BaseJdbcService implements CrosspostSe return list.isEmpty() ? Optional.empty() : list.get(0); } + + @Transactional + @Override + public void deleteVKUser(Integer uid) { + getJdbcTemplate().update("DELETE FROM vk WHERE user_id=?", uid); + } } diff --git a/juick-server/src/main/java/com/juick/service/EmailService.java b/juick-server/src/main/java/com/juick/service/EmailService.java index f62f4b32..67925ec1 100644 --- a/juick-server/src/main/java/com/juick/service/EmailService.java +++ b/juick-server/src/main/java/com/juick/service/EmailService.java @@ -5,4 +5,7 @@ package com.juick.service; */ public interface EmailService { boolean verifyAddressByCode(Integer userId, String code); + boolean addVerificationCode(Integer userId, String account, String code); + boolean deleteEmail(Integer userId, String account); + boolean setSubscriptionHour(Integer userId, String account, String hour); } diff --git a/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java b/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java index bdd78609..b0bf9e20 100644 --- a/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/EmailServiceImpl.java @@ -1,5 +1,6 @@ package com.juick.service; +import org.apache.commons.lang3.StringUtils; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @@ -30,4 +31,22 @@ public class EmailServiceImpl extends BaseJdbcService implements EmailService { } return true; } + + @Override + public boolean addVerificationCode(Integer userId, String account, String code) { + return getJdbcTemplate().update("INSERT INTO auth(user_id,protocol,account,authcode) VALUES (?,'email',?,?)", + userId, account, code) > 0; + } + + @Override + public boolean deleteEmail(Integer userId, String account) { + return getJdbcTemplate().update("DELETE FROM emails WHERE user_id=? AND email=?", userId, account) > 0; + } + + @Override + public boolean setSubscriptionHour(Integer userId, String account, String hour) { + getJdbcTemplate().update("UPDATE emails SET subscr_hour=NULL WHERE user_id=?", userId); + return StringUtils.isNotEmpty(account) && getJdbcTemplate().update( + "UPDATE emails SET subscr_hour=? WHERE user_id=? AND email=?", hour, userId, account) > 0; + } } diff --git a/juick-server/src/main/java/com/juick/service/TelegramService.java b/juick-server/src/main/java/com/juick/service/TelegramService.java index 259ab367..b23e3405 100644 --- a/juick-server/src/main/java/com/juick/service/TelegramService.java +++ b/juick-server/src/main/java/com/juick/service/TelegramService.java @@ -14,6 +14,8 @@ public interface TelegramService { boolean createTelegramUser(long tgID, String tgName); + boolean deleteTelegramUser(Integer uid); + List<Long> getSubscribers(int uid); List<Long> getSubscribersToComments(int mid, int ignore_uid); diff --git a/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java b/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java index 89954944..a698e2e8 100644 --- a/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java +++ b/juick-server/src/main/java/com/juick/service/TelegramServiceImpl.java @@ -49,6 +49,12 @@ public class TelegramServiceImpl extends BaseJdbcService implements TelegramServ tgID, tgName, UUID.randomUUID().toString()) > 0; } + @Transactional + @Override + public boolean deleteTelegramUser(Integer uid) { + return getJdbcTemplate().update("DELETE FROM telegram WHERE user_id=?", uid) > 0; + } + @Transactional(readOnly = true) @Override public List<Long> getSubscribers(final int uid) { diff --git a/juick-spring-www/build.gradle b/juick-spring-www/build.gradle index 56042c5a..c6da5edd 100644 --- a/juick-spring-www/build.gradle +++ b/juick-spring-www/build.gradle @@ -32,6 +32,8 @@ dependencies { compile "org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.1.RELEASE" compile "nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:2.1.2" + compile 'net.coobird:thumbnailator:0.4.8' + testCompile "junit:junit:${rootProject.junitVersion}" testCompile "org.hamcrest:hamcrest-all:${rootProject.hamcrestVersion}" testCompile "org.mockito:mockito-core:1.+" diff --git a/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java b/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java index ceccdbb7..d150d71e 100644 --- a/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java +++ b/juick-spring-www/src/main/java/com/juick/www/controllers/SettingsController.java @@ -1,18 +1,41 @@ package com.juick.www.controllers; import com.juick.User; +import com.juick.server.helpers.NotifyOpts; +import com.juick.server.helpers.UserInfo; +import com.juick.server.util.HttpBadRequestException; +import com.juick.server.util.HttpForbiddenException; +import com.juick.server.util.HttpUtils; import com.juick.service.*; import com.juick.util.UserUtils; +import net.coobird.thumbnailator.Thumbnails; +import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.multipart.MultipartFile; import javax.inject.Inject; -import javax.servlet.ServletException; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.security.Principal; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; @@ -23,6 +46,7 @@ import java.util.stream.IntStream; */ @Controller public class SettingsController { + private static final Logger logger = LoggerFactory.getLogger(SettingsController.class); @Inject UserService userService; @Inject @@ -33,13 +57,16 @@ public class SettingsController { SubscriptionService subscriptionService; @Inject EmailService emailService; + @Inject + TelegramService telegramService; + @Inject + Environment env; - @RequestMapping("settings") + @RequestMapping(value = "settings", method = RequestMethod.GET) public String showSettings( @RequestParam(required = false) String page, @RequestParam(required = false) String code, - ModelMap context - ) throws ServletException, IOException { + ModelMap context) { User visitor = UserUtils.getCurrentUser(); if (visitor.getUid() == 0) { return "redirect:/login"; @@ -71,4 +98,180 @@ public class SettingsController { } return String.format("views/settings_%s", page); } + @RequestMapping(value = "/settings", method = RequestMethod.POST) + protected String doPost( + HttpServletResponse response, + @RequestParam String page, + @RequestParam(required = false) String password, + @RequestParam(required = false) String jnotify, + @RequestParam(required = false) String subscr_notify, + @RequestParam(required = false) String recomm, + @RequestParam(required = false) String fullname, + @RequestParam(required = false) String country, + @RequestParam(required = false) String url, + @RequestParam(required = false) String descr, + @RequestParam(required = false) MultipartFile avatar, + @RequestParam(required = false) String account, + @RequestParam(required = false) String time, + ModelMap context) throws IOException { + User visitor = UserUtils.getCurrentUser(); + if (visitor.getUid() == 0) { + throw new HttpForbiddenException(); + } + List<String> pages = Arrays.asList("main", "password", "about", "email", "email-add", "email-del", + "email-subscr", "auth-email", "privacy", "jid-del", "twitter-del", "telegram-del", "facebook-disable", + "facebook-enable", "vk-del"); + if (StringUtils.isEmpty(page) || !pages.contains(page)) { + throw new HttpBadRequestException(); + } + String result = ""; + switch (page) { + case "password": + if (userService.updatePassword(visitor, password)) { + result = "<p>Password has been changed.</p>"; + String hash = userService.getHashByUID(visitor.getUid()); + Cookie c = new Cookie("hash", hash); + c.setMaxAge(365 * 24 * 60 * 60); + // FIXME: use spring-security + response.addCookie(c); + } + break; + case "main": + NotifyOpts opts = new NotifyOpts(); + opts.setRepliesEnabled(StringUtils.isNotEmpty(jnotify)); + opts.setSubscriptionsEnabled(StringUtils.isNotEmpty(subscr_notify)); + opts.setRecommendationsEnabled(StringUtils.isNotEmpty(recomm)); + if (subscriptionService.setNotifyOptions(visitor, opts)) { + result = "<p>Notification options has been updated</p>"; + } + break; + case "about": + UserInfo info = new UserInfo(); + info.setFullName(fullname); + info.setCountry(country); + info.setUrl(url); + info.setDescription(descr); + String imgPath = env.getProperty("img_path", "/var/www/juick.com/i/"); + String tmpDir = env.getProperty("upload_tmp_dir", + "/var/www/juick.com/i/tmp/"); + String avatarTmpPath = HttpUtils.receiveMultiPartFile(avatar, tmpDir); + if (StringUtils.isNotEmpty(avatarTmpPath)) { + String originalExtension = FilenameUtils.getExtension(avatarTmpPath); + String originalName = String.format("%s.%s", visitor.getUid(), originalExtension); + String targetName = String.format("%s.png", visitor.getUid()); + Path ao = Paths.get(imgPath, "ao", originalName); + Path a = Paths.get(imgPath, "a", targetName); + Path as = Paths.get(imgPath, "as", targetName); + Files.move(Paths.get(tmpDir, avatarTmpPath), ao, StandardCopyOption.REPLACE_EXISTING); + Thumbnails.of(ao.toFile()).size(96, 96).toFile(a.toFile()); + Thumbnails.of(ao.toFile()).size(32, 32).toFile(as.toFile()); + } + if (userService.updateUserInfo(visitor, info)) { + result = String.format("<p>Your info is updated.</p><p><a href='/%s/'>Back to blog</a>.</p>", visitor.getName()); + } + break; + case "jid-del": + // FIXME: stop using ugnich-csv in parameters +// String[] params = request.getParameter("delete").split(";", 2); +// int res = -1; +// if (params[0].equals("xmpp")) { +// res = sql.update("DELETE FROM jids WHERE user_id=? AND jid=?", visitor.getUid(), params[1]); +// } else if (params[0].equals("xmpp-unauth")) { +// res = sql.update("DELETE FROM auth WHERE user_id=? AND protocol='xmpp' AND account=?", visitor.getUid(), params[1]); +// } +// if (res == 1) { +// result = "<p>Deleted. <a href=\"/settings\">Back</a>.</p>"; +// } else { +// result = "<p>Error</p>"; +// } + break; + case "email": + String newHash = userService.updateSecretEmail(visitor); + if (StringUtils.isNotEmpty(newHash)) { + result = String.format("<p>New secret email: <strong>%s@mail.juick.com</strong></p>" + + "<p><a href=\"/settings\">Back</a>.</p>", newHash); + } else { + throw new HttpBadRequestException(); + } + break; + case "email-add": + try { + emailService.verifyAddressByCode(visitor.getUid(), account); + } catch (EmptyResultDataAccessException e) { + String authCode = UserUtils.generateHash(8); + if (emailService.addVerificationCode(visitor.getUid(), account, authCode)) { + Session session = Session.getDefaultInstance(System.getProperties()); + try { + MimeMessage message = new MimeMessage(session); + message.setFrom(new InternetAddress("noreply@mail.juick.com")); + message.addRecipient(Message.RecipientType.TO, new InternetAddress(account)); + message.setSubject("Juick authorization link"); + message.setText(String.format("Follow link to attach this email to Juick account:\n" + + "http://juick.com/settings?page=auth-email&code=%s\n\n" + + "If you don't know, what this mean - just ignore this mail.\n", authCode)); + Transport.send(message); + result = "<p>Authorization link has been sent to your email. Follow it to proceed.</p>" + + "<p><a href=\"/settings\">Back</a></p>"; + + } catch (MessagingException ex) { + logger.error("mail exception", ex); + throw new HttpBadRequestException(); + } + } + } + break; + case "email-del": + if (emailService.deleteEmail(visitor.getUid(), account)) { + result = "<p>Deleted. <a href=\"/settings\">Back</a>.</p>"; + } else { + result = "<p>An error occured while deleting.</p>"; + } + break; + case "email-subscr": + if (emailService.setSubscriptionHour(visitor.getUid(), account, time)) { + result = String.format("<p>Saved! Will send to <strong>%s</strong> at <strong>%s:00 GMT</strong>." + + "</p><p><a href=\"/settings\">Back</a></p>", account, time); + } else { + result = "<p>Disabled.</p><p><a href=\"/settings\">Back</a></p>"; + } + break; + case "twitter-del": + crosspostService.deleteTwitterToken(visitor.getUid()); + // FIXME: use spring-security +// for (Cookie cookie : request.getCookies()) { +// if (cookie.getName().equals("request_token")) { +// cookie.setMaxAge(0); +// response.addCookie(cookie); +// } +// if (cookie.getName().equals("request_token_secret")) { +// cookie.setMaxAge(0); +// response.addCookie(cookie); +// } +// } + result = "<p><a href=\"/settings\">Back</a></p>"; + break; + case "telegram-del": + telegramService.deleteTelegramUser(visitor.getUid()); + result = "<p><a href=\"/settings\">Back</a></p>"; + break; + case "facebook-disable": + crosspostService.disableFBCrosspost(visitor.getUid()); + result = "<p><a href=\"/settings\">Back</a></p>"; + break; + case "facebook-enable": + crosspostService.enableFBCrosspost(visitor.getUid()); + result = "<p><a href=\"/settings\">Back</a></p>"; + break; + case "vk-del": + crosspostService.deleteVKUser(visitor.getUid()); + result = "<p><a href=\"/settings\">Back</a></p>"; + break; + default: + throw new HttpBadRequestException(); + } + context.put("title", "Настройки"); + context.put("visitor", visitor); + context.put("result", result); + return "views/settings_result"; + } } diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_inbox.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_inbox.html index 7ab557f5..7de997b8 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_inbox.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_inbox.html @@ -12,10 +12,10 @@ <li class="msg" th:each="msg:${msgs}"> <div class="msg-cont"> <div class="msg-header"> - @<a href="/${msg.getUser().getName()}/" th:text="${msg.getUser().getName()}">ugnich</a>: + @<a th:href="|/${msg.getUser().getName()}/|" th:text="${msg.getUser().getName()}">ugnich</a>: <div class="msg-avatar"> - <a href="/${msg.getUser().getName()}/"> - <img src="//i.juick.com/a/${msg.getUser().getUid()}.png" alt="${msg.getUser().getName()}"/> + <a th:href="|/${msg.getUser().getName()}/|"> + <img th:src="|//i.juick.com/a/${msg.getUser().getUid()}.png|" th:alt="${msg.getUser().getName()}"/> </a> </div> <div class="msg-ts" th:text="${msg.getDate()}">01.01.1970</div> @@ -37,7 +37,7 @@ </ul> </section> <aside id="column"> - <p th:replace="views/partial/homecolumn.html">Main side column</p> + <p layout:fragment="column" th:replace="views/partial/homecolumn">Main side column</p> </aside> </body> diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_sent.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_sent.html index f2c05ad3..8978ff67 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_sent.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/pm_sent.html @@ -20,10 +20,10 @@ <li class="msg" th:each="msg:${msgs}"> <div class="msg-cont"> <div class="msg-header"> - @<a href="/${msg.getUser().getName()}/" th:text="${msg.getUser().getName()}">ugnich</a>: + @<a th:href="|/${msg.getUser().getName()}/|" th:text="${msg.getUser().getName()}">ugnich</a>: <div class="msg-avatar"> - <a href="/${msg.getUser().getName()}/"> - <img src="//i.juick.com/a/${msg.getUser().getUid()}.png" alt="${msg.getUser().getName()}"/> + <a th:href="|/${msg.getUser().getName()}/|"> + <img th:src="|//i.juick.com/a/${msg.getUser().getUid()}.png|" th:alt="${msg.getUser().getName()}"/> </a> </div> <div class="msg-ts" th:text="${msg.getDate()}">01.01.1970</div> @@ -35,7 +35,7 @@ </div> </section> <aside id="column"> - <p th:replace="views/partial/homecolumn.html">Main side column</p> + <p layout:fragment="column" th:replace="views/partial/homecolumn">Main side column</p> </aside> </body> diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_about.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_about.html index b93a699e..6f8f61dd 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_about.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_about.html @@ -10,12 +10,12 @@ <section id="content"> <article layout:fragment="content"> <form action="/settings" method="POST" enctype="multipart/form-data"> - <p>Full name: <input type="text" name="fullname" value="${userinfo.getFullName()}"/></p> - <p>Country: <input type="text" name="country" value="${userinfo.getCountry()}"/></p> - <p>URL: <input type="text" name="url" value="${userinfo.getUrl()}" size="32"/><br/> + <p>Full name: <input type="text" name="fullname" th:value="${userinfo.getFullName()}"/></p> + <p>Country: <input type="text" name="country" th:value="${userinfo.getCountry()}"/></p> + <p>URL: <input type="text" name="url" th:value="${userinfo.getUrl()}" size="32"/><br/> <small>Please, start with "http://"</small></p> <p>About:<br/> - <input type="text" name="descr" value="${userinfo.getDescription()}" style="width: 100%"/><br/> + <input type="text" name="descr" th:value="${userinfo.getDescription()}" style="width: 100%"/><br/> <small>Max. 255 symbols</small></p> <p>Avatar: <input type="file" name="avatar"/><br/> <small>Recommendations: PNG, 96x96, <50Kb. Also, JPG and GIF supported.</small></p> @@ -24,7 +24,7 @@ </article> </section> <aside id="column"> - <p th:replace="views/partial/settings/tabs">Settings navigation</p> + <p layout:fragment="column" th:replace="views/partial/settings_tabs">Settings navigation</p> </aside> </body> diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_auth-email.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_auth-email.html index d4788fd6..715d474d 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_auth-email.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_auth-email.html @@ -13,7 +13,7 @@ </article> </section> <aside id="column"> - <p th:replace="views/partial/settings/tabs">Settings navigation</p> + <p layout:fragment="column" th:replace="views/partial/settings_tabs">Settings navigation</p> </aside> </body> diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_main.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_main.html index 42eff2e3..2db977f4 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_main.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_main.html @@ -13,29 +13,27 @@ <form action="/settings" method="POST" enctype="multipart/form-data"> <fieldset> <legend>Notification options</legend> - <p><input type="checkbox" name="jnotify" value="1" {% if notify_options.isRepliesEnabled() %} - checked="checked" {% endif %}/> Reply notifications ("Message posted")</p> - <p><input type="checkbox" name="subscr_notify" value="1" {% if notify_options.isSubscriptionsEnabled() %} - checked="checked" {% endif %}/> Subscriptions notifications ("@user subscribed...")</p> - <p><input type="checkbox" name="recomm" value="1" {% if notify_options.isRecommendationsEnabled() %} - checked="checked" {% endif %}/> Posts recommendations ("Recommended by @user")</p> + <p><input type="checkbox" name="jnotify" value="1" + th:checked="${notify_options.isRepliesEnabled()}"/> Reply notifications ("Message posted")</p> + <p><input type="checkbox" name="subscr_notify" value="1" + th:checked="${notify_options.isSubscriptionsEnabled()}"/> Subscriptions notifications ("@user subscribed...")</p> + <p><input type="checkbox" name="recomm" value="1" + th:checked="${notify_options.isRecommendationsEnabled()}"/> Posts recommendations ("Recommended by @user")</p> <p><input type="hidden" name="page" value="main"/><input type="submit" value=" OK "/></p> </fieldset> </form> <fieldset> <legend style="background: url(//telegram.org/favicon.ico?3) no-repeat; padding-left: 58px; line-height: 48px;"> Telegram</legend> - {% if telegram_name is not empty %} - <form action="/settings" method="post"> - <div>Telegram: <b>{{ telegram_name }}</b> — + <form action="/settings" method="post" th:if="${telegram_name != null}"> + <div>Telegram: <b th:text="${telegram_name}">telegram_name</b> — <input type="hidden" name="page" value="telegram-del"/> <input type="submit" value=" Disable "/> </div> </form> - {% else %} - <p>To connect Telegram account: send any text message to <a href="https://telegram.me/Juick_bot">@Juick_bot</a> + <p th:if="${telegram_name == null}"> + To connect Telegram account: send any text message to <a href="https://telegram.me/Juick_bot">@Juick_bot</a> </p> - {% endif %} </fieldset> <form action="/settings" method="POST" enctype="multipart/form-data"> <fieldset> @@ -44,19 +42,17 @@ </legend> <p>Your accounts:</p> <p> - {% for jid in jids %} - <label><input type="radio" name="delete" value="xmpp;{{ jid }}">{{ jid }}</label><br/> - {% endfor %} - {% for auth in auths %} + <th:block th:each="jid:${jids}"> + <label><input type="radio" name="delete" th:value="|xmpp;${jid}}" th:text="${jid}">username@jabber.ru</label><br/> + </th:block> + <th:block th:each="auth:${auths}"> <label><input type="radio" name="delete" - value="xmpp-unauth;{{ auth.getAccount() }}">{{ auth.getAccount() }}</label> + th:value="|xmpp-unauth;${auth.getAccount()}|" th:text="${auth.getAccount()}">account</label> — <a href="#" onclick="alert(\'To confirm, please send "AUTH {{ auth.getAuthCode() }}" (without quotes) from this account to "juick@juick.com".\'); return false;">Confirm</a><br/> - {% endfor %} + </th:block> </p> - {% if jids is not empty %} - <p><input type="hidden" name="page" value="jid-del"/><input type="submit" value=" Delete "/></p> - {% endif %} + <p th:if="#{not lists.isEmpty(jids)}"><input type="hidden" name="page" value="jid-del"/><input type="submit" value=" Delete "/></p> <p>To add new jabber account: send any text message to <a href="xmpp:juick@juick.com?message;body=login">juick@juick.com</a> </p> </fieldset> @@ -75,42 +71,37 @@ <form action="/settings" method="POST" enctype="multipart/form-data"> <p>Your accounts:</p> <p> - {% for email in emails %} - <label><input type="radio" name="account" value="{{ email }}">{{ email }}</label><br/> - {% endfor %} - {% if emails is empty %} - - </p> - {% else %} - </p> - <p><input type="hidden" name="page" value="email-del"/><input type="submit" value=" Delete "/></p> - {% endif %} + <th:block th:each="email:${emails}"> + <label><input type="radio" name="account" th:value="${email}" th:text="${email}">email@domain.tls</label><br/> + </th:block> + <p th:if="#{lists.isEmpty(emails)}"> + -</p> + <th:block th:if="#{not lists.isEmpty(emails)}"> + </p> + <p><input type="hidden" name="page" value="email-del"/><input type="submit" value=" Delete "/></p> + </th:block> </form> - {% if emails is not empty %} - <form action="/settings" method="POST" enctype="multipart/form-data"> + <form action="/settings" method="POST" enctype="multipart/form-data" th:if="#{not lists.isEmpty(emails)}"> <p>You can receive all your subscriptions by email:<br/> Sent to <select name="account"> <option value="">Disabled</option> - {% for email in emails %} - <option value="{{ email }}" {% if eopts.getEmail()== email %} selected="selected" {% endif %}> - {{ email }} + <option th:each="email:${emails}" th:value="${email}" th:text="${email}" + th:selected="${eopts.getEmail()== email}"> </option> - {% endfor %} </select> every day at <select name="time"> - {% for hour in hours %} - <option value="{{ hour }}" {% if eopts.getSubscriptionHour() == hour %} selected="selected" {% - endif %}> - {{ hour }}:00 GMT + <th:block th:each="hour:${hours}"> + <option th:value="${hour}" th:selected="${eopts.getSubscriptionHour() == hour}" + th:text="|${hour}:00 GMT|"> </option> - {% endfor %} + </th:block> </select> <input type="hidden" name="page" value="email-subscr"/> <input type="submit" value="OK"/></p> </form> - {% endif %} <p> </p> <p>You can post to Juick via e-mail. Send your <span style="text-decoration: underline">plain text</span> messages to special secret e-mail. You can attach one photo or video file.</p> - <p>Secret email: {% if ehash is not empty %} <strong>{{ ehash }}</strong> {% else %}-{% endif %}</p> + <p>Secret email: <strong th:if="${ehash != null}" th:text="${ehash}">SecretEmail@juick.com</strong><th:block th:if="${ehash == null}">-</th:block></p> <form action="/settings" method="post"> <p><input type="hidden" name="page" value="email"/><input type="submit" value=" Generate new "/></p> </form> @@ -119,48 +110,43 @@ <legend style="background: url(//static.juick.com/settings/facebook.png) no-repeat; padding-left: 58px; line-height: 48px;"> Facebook </legend> - {% if fbstatus.isConnected() %} - {% if fbstatus.isCrosspostEnabled() %} - <form action="/settings" method="post"> + <form action="/settings" method="post" th:if="${fbstatus.isConnected() && fbstatus.isCrosspostEnabled()}"> <div> Facebook: <b>Enabled</b> — <input type="hidden" name="page" value="facebook-disable"/> <input type="submit" value=" Disable "/> </div> </form> - {% else %} - <form action="/settings" method="post"> + <form action="/settings" method="post" th:if="${fbstatus.isConnected() && !fbstatus.isCrosspostEnabled()}"> <div> Facebook: <b>Disabled</b> — <input type="hidden" name="page" value="facebook-enable"/> <input type="submit" value=" Enable "/> </div> </form> - {% endif %} - {% else %} - <p>Cross-posting to Facebook: <a href="/_fblogin"><img src="//static.juick.com/facebook-connect.png" alt="Connect to Facebook"/></a></p> - {% endif %} + <p th:if="${!fbstatus.isConnected()}">Cross-posting to Facebook: + <a href="/_fblogin"> + <img src="//static.juick.com/facebook-connect.png" alt="Connect to Facebook"/> + </a> + </p> </fieldset> <fieldset> <legend style="background: url(//static.juick.com/settings/twitter.png) no-repeat; padding-left: 58px; line-height: 48px;"> Twitter</legend> - {% if twitter_name is not empty %} - <form action="/settings" method="post"> - <div>Twitter: <b>{{ twitter_name }}</b> — + <form action="/settings" method="post" th:if="${twitter_name != null}"> + <div>Twitter: <b th:text="${twitter_name}">@twitterName</b> — <input type="hidden" name="page" value="twitter-del"/> <input type="submit" value=" Disable "/> </div> </form> - {% else %} - <p>Cross-posting to Twitter: <a href="/_twitter"><img src="//static.juick.com/twitter-connect.png" + <p th:if="${twitter_name == null}">Cross-posting to Twitter: <a href="/_twitter"><img src="//static.juick.com/twitter-connect.png" alt="Connect to Twitter"/></a></p> - {% endif %} </fieldset> </article> </section> <aside id="column"> - <p th:replace="views/partial/settings/tabs">Settings navigation</p> + <p layout:fragment="column" th:replace="views/partial/settings_tabs">Settings navigation</p> </aside> </body> diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_password.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_password.html index 4c6e0d4d..d1e7e075 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_password.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_password.html @@ -19,7 +19,7 @@ </fieldset> </section> <aside id="column"> - <p th:replace="views/partial/settings/tabs">Settings navigation</p> + <p layout:fragment="column" th:replace="views/partial/settings_tabs">Settings navigation</p> </aside> </body> diff --git a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_result.html b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_result.html index ddde1baf..20cb097d 100644 --- a/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_result.html +++ b/juick-spring-www/src/main/webapp/WEB-INF/templates/views/settings_result.html @@ -8,10 +8,10 @@ <body> <section id="content"> - <p th:utext="${result}">Settings update status</p> + <p layout:fragment="content" th:utext="${result}">Settings update status</p> </section> <aside id="column"> - <p th:replace="views/partial/settings/tabs">Settings navigation</p> + <p layout:fragment="column" th:replace="views/partial/settings_tabs">Settings navigation</p> </aside> </body> |