Merge pull request #153 from Doha2012/master

add schedule post to reddit
This commit is contained in:
Eugen
2015-03-02 22:03:51 +02:00
19 changed files with 2520 additions and 33 deletions
@@ -23,6 +23,9 @@ import org.springframework.util.MultiValueMap;
public class MyAuthorizationCodeAccessTokenProvider extends AuthorizationCodeAccessTokenProvider implements Serializable {
/**
*
*/
private static final long serialVersionUID = 3822611002661972274L;
private StateKeyGenerator stateKeyGenerator = new DefaultStateKeyGenerator();
@@ -0,0 +1,75 @@
package org.baeldung.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence.properties" })
@ComponentScan({ "org.baeldung.persistence" })
@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
public class PersistenceJPAConfig {
@Autowired
private Environment env;
public PersistenceJPAConfig() {
super();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
@Bean
public JpaTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
return hibernateProperties;
}
}
@@ -13,7 +13,7 @@ public class ServletInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebConfig.class);
context.register(PersistenceJPAConfig.class, WebConfig.class);
return context;
}
@@ -2,12 +2,15 @@ package org.baeldung.config;
import java.util.Arrays;
import org.baeldung.web.schedule.ScheduledTasks;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
@@ -27,7 +30,9 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "org.baeldung.web" })
@EnableScheduling
@EnableAsync
@ComponentScan({ "org.baeldung.web" })
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
@@ -48,6 +53,25 @@ public class WebConfig extends WebMvcConfigurerAdapter {
configurer.enable();
}
// @Bean
// public RedditController redditController(OAuth2RestTemplate redditRestTemplate) {
// RedditController controller = new RedditController();
// controller.setRedditRestTemplate(redditRestTemplate);
// return controller;
// }
//
// @Bean
// public RestExceptionHandler restExceptionHandler() {
// return new RestExceptionHandler();
// }
//
@Bean
public ScheduledTasks scheduledTasks(OAuth2ProtectedResourceDetails reddit) {
ScheduledTasks s = new ScheduledTasks();
s.setRedditRestTemplate(new OAuth2RestTemplate(reddit));
return s;
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@@ -0,0 +1,15 @@
package org.baeldung.persistence.dao;
import java.util.Date;
import java.util.List;
import org.baeldung.persistence.model.Post;
import org.baeldung.persistence.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostRepository extends JpaRepository<Post, Long> {
public List<Post> findBySubmissionDateBefore(Date date);
public List<Post> findByUser(User user);
}
@@ -0,0 +1,10 @@
package org.baeldung.persistence.dao;
import org.baeldung.persistence.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
public User findByUsername(String username);
public User findByAccessToken(String token);
}
@@ -0,0 +1,103 @@
package org.baeldung.persistence.model;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String subreddit;
private String url;
private Date submissionDate;
private boolean isSent;
private String submissionResponse;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
public Post() {
super();
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getSubreddit() {
return subreddit;
}
public void setSubreddit(String subreddit) {
this.subreddit = subreddit;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Date getSubmissionDate() {
return submissionDate;
}
public void setSubmissionDate(Date submissionDate) {
this.submissionDate = submissionDate;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public boolean isSent() {
return isSent;
}
public void setSent(boolean isSent) {
this.isSent = isSent;
}
public String getSubmissionResponse() {
return submissionResponse;
}
public void setSubmissionResponse(String submissionResponse) {
this.submissionResponse = submissionResponse;
}
}
@@ -0,0 +1,104 @@
package org.baeldung.persistence.model;
import java.util.Date;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
private String accessToken;
private String refreshToken;
private Date tokenExpiration;
@OneToMany(mappedBy = "user")
private List<Post> posts;
public User() {
super();
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public Date getTokenExpiration() {
return tokenExpiration;
}
public void setTokenExpiration(Date tokenExpiration) {
this.tokenExpiration = tokenExpiration;
}
public List<Post> getPosts() {
return posts;
}
public void setPosts(List<Post> posts) {
this.posts = posts;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((username == null) ? 0 : username.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final User user = (User) obj;
if (!username.equals(user.username))
return false;
return true;
}
}
@@ -1,15 +1,21 @@
package org.baeldung.web;
import java.io.IOException;
import java.util.ArrayList;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.baeldung.persistence.dao.PostRepository;
import org.baeldung.persistence.dao.UserRepository;
import org.baeldung.persistence.model.Post;
import org.baeldung.persistence.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
@@ -17,37 +23,43 @@ import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller
public class RedditController {
private final Logger logger = LoggerFactory.getLogger(getClass());
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
@Autowired
private OAuth2RestTemplate redditRestTemplate;
// API
@Autowired
private UserRepository userReopsitory;
@Autowired
private PostRepository postReopsitory;
@RequestMapping("/info")
public final String getInfo(Model model) {
final JsonNode node = redditRestTemplate.getForObject("https://oauth.reddit.com/api/v1/me", JsonNode.class);
final String name = node.get("name").asText();
JsonNode node = redditRestTemplate.getForObject("https://oauth.reddit.com/api/v1/me", JsonNode.class);
String name = node.get("name").asText();
addUser(name, redditRestTemplate.getAccessToken());
model.addAttribute("info", name);
return "reddit";
}
@RequestMapping("/submit")
public final String submit(Model model, @RequestParam Map<String, String> formParams) {
final MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
param.add("api_type", "json");
param.add("kind", "link");
param.add("resubmit", "true");
param.add("sendreplies", "false");
param.add("then", "comments");
for (final Map.Entry<String, String> entry : formParams.entrySet()) {
for (Map.Entry<String, String> entry : formParams.entrySet()) {
param.add(entry.getKey(), entry.getValue());
}
@@ -60,44 +72,73 @@ public class RedditController {
}
@RequestMapping("/post")
public final String showSubmissionForm(final Model model) {
final String needsCaptchaResult = needsCaptcha();
public final String showSubmissionForm(Model model) {
String needsCaptchaResult = needsCaptcha();
if (needsCaptchaResult.equalsIgnoreCase("true")) {
final String iden = getNewCaptcha();
String iden = getNewCaptcha();
model.addAttribute("iden", iden);
}
return "submissionForm";
}
// === private
final List<String> getSubreddit() throws JsonProcessingException, IOException {
final String result = redditRestTemplate.getForObject("https://oauth.reddit.com/subreddits/popular?limit=50", String.class);
final JsonNode node = new ObjectMapper().readTree(result).get("data").get("children");
final List<String> subreddits = new ArrayList<String>();
for (JsonNode child : node) {
subreddits.add(child.get("data").get("display_name").asText());
@RequestMapping("/postSchedule")
public final String showSchedulePostForm(Model model) {
String needsCaptchaResult = needsCaptcha();
if (needsCaptchaResult.equalsIgnoreCase("true")) {
model.addAttribute("msg", "Sorry, You do not have enought karma");
return "submissionResponse";
}
return subreddits;
return "schedulePostForm";
}
@RequestMapping("/schedule")
public final String schedule(Model model, @RequestParam Map<String, String> formParams) throws ParseException {
logger.info("User scheduling Post with these parameters: " + formParams.entrySet());
User user = userReopsitory.findByAccessToken(redditRestTemplate.getAccessToken().getValue());
Post post = new Post();
post.setUser(user);
post.setSent(false);
post.setTitle(formParams.get("title"));
post.setSubreddit(formParams.get("sr"));
post.setUrl(formParams.get("url"));
post.setSubmissionDate(dateFormat.parse(formParams.get("date")));
if (post.getSubmissionDate().before(new Date())) {
model.addAttribute("msg", "Invalid date");
return "submissionResponse";
}
postReopsitory.save(post);
List<Post> posts = postReopsitory.findByUser(user);
model.addAttribute("posts", posts);
return "postListView";
}
@RequestMapping("/posts")
public final String getScheduledPosts(Model model) {
User user = userReopsitory.findByAccessToken(redditRestTemplate.getAccessToken().getValue());
List<Post> posts = postReopsitory.findByUser(user);
model.addAttribute("posts", posts);
return "postListView";
}
// === private
private final String needsCaptcha() {
String result = redditRestTemplate.getForObject("https://oauth.reddit.com/api/needs_captcha.json", String.class);
return result;
}
private final String getNewCaptcha() {
final Map<String, String> param = new HashMap<String, String>();
Map<String, String> param = new HashMap<String, String>();
param.put("api_type", "json");
final String result = redditRestTemplate.postForObject("https://oauth.reddit.com/api/new_captcha", param, String.class, param);
final String[] split = result.split("\"");
String result = redditRestTemplate.postForObject("https://oauth.reddit.com/api/new_captcha", param, String.class, param);
String[] split = result.split("\"");
return split[split.length - 2];
}
private final String parseResponse(final JsonNode node) {
private final String parseResponse(JsonNode node) {
String result = "";
final JsonNode errorNode = node.get("json").get("errors").get(0);
JsonNode errorNode = node.get("json").get("errors").get(0);
if (errorNode != null) {
for (JsonNode child : errorNode) {
result = result + child.toString().replaceAll("\"|null", "") + "<br>";
@@ -111,4 +152,16 @@ public class RedditController {
}
}
private final void addUser(String name, OAuth2AccessToken token) {
User user = userReopsitory.findByUsername(name);
if (user == null) {
user = new User();
user.setUsername(name);
user.setAccessToken(token.getValue());
user.setRefreshToken(token.getRefreshToken().getValue());
user.setTokenExpiration(token.getExpiration());
userReopsitory.save(user);
}
}
}
@@ -14,6 +14,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
@ControllerAdvice
public class RestExceptionHandler extends ResponseEntityExceptionHandler implements Serializable {
private static final long serialVersionUID = -3861125729653781371L;
public RestExceptionHandler() {
@@ -36,5 +37,4 @@ public class RestExceptionHandler extends ResponseEntityExceptionHandler impleme
String response = "Error Occurred : " + ex.getMessage();
return handleExceptionInternal(ex, response, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}
@@ -0,0 +1,77 @@
package org.baeldung.web.schedule;
import java.io.IOException;
import java.text.ParseException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.baeldung.persistence.dao.PostRepository;
import org.baeldung.persistence.model.Post;
import org.baeldung.persistence.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
@EnableScheduling
public class ScheduledTasks {
private OAuth2RestTemplate redditRestTemplate;
@Autowired
private PostRepository postReopsitory;
@Scheduled(fixedRate = 5 * 60 * 1000)
public void reportCurrentTime() throws JsonProcessingException, IOException, ParseException {
List<Post> posts = postReopsitory.findBySubmissionDateBefore(new Date());
System.out.println(posts.size());
for (Post post : posts) {
if (post.isSent())
continue;
User user = post.getUser();
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(user.getAccessToken());
token.setRefreshToken(new DefaultOAuth2RefreshToken((user.getRefreshToken())));
token.setExpiration(user.getTokenExpiration());
redditRestTemplate.getOAuth2ClientContext().setAccessToken(token);
//
UsernamePasswordAuthenticationToken userAuthToken = new UsernamePasswordAuthenticationToken(user.getUsername(), token.getValue(), Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
SecurityContextHolder.getContext().setAuthentication(userAuthToken);
//
MultiValueMap<String, String> param = new LinkedMultiValueMap<String, String>();
param.add("api_type", "json");
param.add("kind", "link");
param.add("resubmit", "true");
param.add("sendreplies", "false");
param.add("then", "comments");
param.add("title", post.getTitle());
param.add("sr", post.getSubreddit());
param.add("url", post.getUrl());
JsonNode node = redditRestTemplate.postForObject("https://oauth.reddit.com/api/submit", param, JsonNode.class);
JsonNode errorNode = node.get("json").get("errors").get(0);
if (errorNode == null) {
post.setSent(true);
postReopsitory.save(post);
} else {
post.setSubmissionResponse(errorNode.toString());
postReopsitory.save(post);
}
}
}
public void setRedditRestTemplate(OAuth2RestTemplate redditRestTemplate) {
this.redditRestTemplate = redditRestTemplate;
}
}
@@ -0,0 +1,10 @@
################### DataSource Configuration ##########################
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/oauth_reddit?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql
init-db=false
################### Hibernate Configuration ##########################
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
@@ -0,0 +1,54 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Spring Security OAuth</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="info">Spring Security OAuth</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">My Scheduled Posts</a></li>
<li><a href="post">Submit Post</a></li>
<li><a href="postSchedule">Schedule Post</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<h1>My Scheduled Posts</h1>
<table class="table table-bordered">
<c:forEach var="post" items="${posts}" >
<thead>
<tr>
<th>Post title</th>
<th>Submission Date</th>
<th>Notes</th>
</tr>
</thead>
<tr <c:if test="${post.isSent()}"> class="success"</c:if>>
<td><c:out value="${post.getTitle()}"/></td>
<td><c:out value="${post.getSubmissionDate()}"/></td>
<td><c:out value="${post.getSubmissionResponse()}"/></td>
</tr>
</c:forEach>
</table>
</div>
</body>
</html>
@@ -7,12 +7,34 @@
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Spring Security OAuth</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="posts">My Scheduled Posts</a></li>
<li><a href="post">Submit Post</a></li>
<li><a href="postSchedule">Schedule Post</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<c:choose>
<c:when test="${info != null}">
<h1>Your Reddit Info</h1>
<b>Your reddit username is </b>${info}
<br><br><br>
<h1>Welcome, <small>${info}</small></h1>
<a href="post" class="btn btn-primary">Submit to Reddit</a>
</c:when>
<c:otherwise>
@@ -0,0 +1,71 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Spring Security OAuth</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<link rel="stylesheet" href="<c:url value="/resources/datetime-picker.css" />">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="<c:url value="/resources/datetime-picker.js" />"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Spring Security OAuth</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="posts">My Scheduled Posts</a></li>
<li><a href="post">Submit Post</a></li>
<li class="active"><a href="#">Schedule Post</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<h1>Schedule Post</h1>
<form action="schedule" method="post">
<div class="row">
<div class="form-group">
<label class="col-sm-3">Title</label>
<span class="col-sm-9"><input name="title" placeholder="title" class="form-control" /></span>
</div>
<br><br>
<div class="form-group">
<label class="col-sm-3">Url</label>
<span class="col-sm-9"><input name="url" placeholder="url" class="form-control" /></span>
</div>
<br><br>
<div class="form-group">
<label class="col-sm-3">Subreddit</label>
<span class="col-sm-9"><input name="sr" placeholder="Subreddit" class="form-control" /></span>
</div>
<br><br>
<label class="col-sm-3">Submission Date</label>
<span class="col-sm-9"><input type="text" name="date" class="form-control"></span>
<script type="text/javascript">
$(function(){
$('*[name=date]').appendDtpicker({"inline": true});
});
</script>
<br><br>
<button type="submit" class="btn btn-primary">Post</button>
</div>
</form>
</div>
</body>
</html>
@@ -7,6 +7,30 @@
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Spring Security OAuth</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="posts">My Scheduled Posts</a></li>
<li class="active"><a href="#">Submit Post</a></li>
<li><a href="postSchedule">Schedule Post</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<h1>Submit to Reddit</h1>
<form action="submit" method="post">
@@ -7,9 +7,32 @@
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Spring Security OAuth</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="posts">My Scheduled Posts</a></li>
<li><a href="post">Submit Post</a></li>
<li><a href="postSchedule">Schedule Post</a></li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<div class="container">
<h1>${msg}</h1>
<a href="post" class="btn btn-primary">Submit another link to Reddit</a>
</div>
</body>
</html>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff