Skip to content

Country prediction during series creation #547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/main/java/ru/mystamps/web/Url.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public final class Url {
public static final String ADD_IMAGE_SERIES_PAGE = "/series/{id}/image";
public static final String SEARCH_SERIES_BY_CATALOG = "/series/search/by_catalog";

public static final String SUGGEST_SERIES_COUNTRY = "/suggest/series_country";

public static final String ADD_CATEGORY_PAGE = "/category/add";
public static final String LIST_CATEGORIES_PAGE = "/category/list";
public static final String INFO_CATEGORY_PAGE = "/category/{slug}";
Expand All @@ -77,7 +79,7 @@ public final class Url {
public static final String ADD_SERIES_WITH_COUNTRY_PAGE = "/series/add/country/{slug}";

// MUST be updated when any of our resources were modified
public static final String RESOURCES_VERSION = "v0.3.0";
public static final String RESOURCES_VERSION = "v0.3.1";

// CheckStyle: ignore LineLength for next 4 lines
public static final String MAIN_CSS = "/static/" + RESOURCES_VERSION + "/styles/main.min.css";
Expand Down Expand Up @@ -125,6 +127,7 @@ public static Map<String, String> asMap(boolean serveContentFromSingleHost) {
map.put("INFO_SERIES_PAGE", INFO_SERIES_PAGE);
map.put("ADD_IMAGE_SERIES_PAGE", ADD_IMAGE_SERIES_PAGE);
map.put("SEARCH_SERIES_BY_CATALOG", SEARCH_SERIES_BY_CATALOG);
map.put("SUGGEST_SERIES_COUNTRY", SUGGEST_SERIES_COUNTRY);
map.put("ADD_CATEGORY_PAGE", ADD_CATEGORY_PAGE);
map.put("INFO_CATEGORY_PAGE", INFO_CATEGORY_PAGE);
map.put("LIST_CATEGORIES_PAGE", LIST_CATEGORIES_PAGE);
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/ru/mystamps/web/config/ControllersConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,13 @@ public SiteController getSiteController() {
public SitemapController getSitemapController() {
return new SitemapController(servicesConfig.getSeriesService());
}


@Bean
public SuggestionController getSuggestionController() {
return new SuggestionController(
servicesConfig.getCountryService()
);
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2009-2017 Slava Semushin <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package ru.mystamps.web.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import lombok.RequiredArgsConstructor;

import ru.mystamps.web.Url;
import ru.mystamps.web.controller.converter.annotation.CurrentUser;
import ru.mystamps.web.service.CountryService;

@Controller
@RequiredArgsConstructor
public class SuggestionController {

private final CountryService countryService;

/**
* @author John Shkarin
*/
@ResponseBody
@GetMapping(Url.SUGGEST_SERIES_COUNTRY)
public String suggestCountryForUser(@CurrentUser Integer currentUserId) {
return countryService.suggestCountryForUser(currentUserId);
}

}

3 changes: 3 additions & 0 deletions src/main/java/ru/mystamps/web/dao/CountryDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import ru.mystamps.web.dao.dto.AddCountryDbDto;
import ru.mystamps.web.dao.dto.LinkEntityDto;

@SuppressWarnings("PMD.TooManyMethods")
public interface CountryDao {
Integer add(AddCountryDbDto country);
long countAll();
Expand All @@ -35,4 +36,6 @@ public interface CountryDao {
List<Object[]> getStatisticsOf(Integer collectionId, String lang);
List<LinkEntityDto> findAllAsLinkEntities(String lang);
LinkEntityDto findOneAsLinkEntity(String slug, String lang);

String suggestCountryForUser(Integer userId);
}
31 changes: 29 additions & 2 deletions src/main/java/ru/mystamps/web/dao/impl/JdbcCountryDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import ru.mystamps.web.dao.dto.LinkEntityDto;

@RequiredArgsConstructor
@SuppressWarnings("PMD.AvoidDuplicateLiterals")
@SuppressWarnings({"PMD.AvoidDuplicateLiterals", "PMD.TooManyMethods"})
public class JdbcCountryDao implements CountryDao {

private final NamedParameterJdbcTemplate jdbcTemplate;
Expand Down Expand Up @@ -76,6 +76,12 @@ public class JdbcCountryDao implements CountryDao {

@Value("${country.find_country_link_info_by_slug}")
private String findCountryLinkEntityBySlugSql;

@Value("${country.find_last_country_by_id}")
private String findLastCountryByIdSql;

@Value("${country.find_popular_country}")
private String findPopularCountrySql;

@Override
public Integer add(AddCountryDbDto country) {
Expand Down Expand Up @@ -206,5 +212,26 @@ public LinkEntityDto findOneAsLinkEntity(String slug, String lang) {
return null;
}
}


@Override
public String suggestCountryForUser(Integer userId) {

try {
return jdbcTemplate.queryForObject(
findLastCountryByIdSql,
Collections.singletonMap("created_by", userId),
String.class);
} catch (EmptyResultDataAccessException ignored) {
try {
return jdbcTemplate.queryForObject(
findPopularCountrySql,
Collections.<String, Object>emptyMap(),
String.class
);

} catch (EmptyResultDataAccessException ex) {
return null;
}
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/ru/mystamps/web/service/CountryService.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import ru.mystamps.web.dao.dto.LinkEntityDto;
import ru.mystamps.web.service.dto.AddCountryDto;

@SuppressWarnings("PMD.TooManyMethods")
public interface CountryService {
String add(AddCountryDto dto, Integer userId);
String suggestCountryForUser(Integer userId);
List<LinkEntityDto> findAllAsLinkEntities(String lang);
LinkEntityDto findOneAsLinkEntity(String slug, String lang);
long countAll();
Expand Down
14 changes: 13 additions & 1 deletion src/main/java/ru/mystamps/web/service/CountryServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import ru.mystamps.web.util.SlugUtils;

@RequiredArgsConstructor
@SuppressWarnings("PMD.TooManyMethods")
public class CountryServiceImpl implements CountryService {
private static final Logger LOG = LoggerFactory.getLogger(CountryServiceImpl.class);

Expand Down Expand Up @@ -162,5 +163,16 @@ public List<Object[]> getStatisticsOf(Integer collectionId, String lang) {

return countryDao.getStatisticsOf(collectionId, lang);
}


/**
* @author Shkarin John
*/
@Override
@Transactional(readOnly = true)
@PreAuthorize(HasAuthority.CREATE_SERIES)
public String suggestCountryForUser(Integer userId) {
Validate.isTrue(userId != null, "User id must be non null");

return countryDao.suggestCountryForUser(userId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ protected void configure(HttpSecurity http) throws Exception {
.mvcMatchers(Url.ADD_COUNTRY_PAGE).hasAuthority(StringAuthority.CREATE_COUNTRY)
.mvcMatchers(Url.ADD_SERIES_PAGE).hasAuthority(StringAuthority.CREATE_SERIES)
.mvcMatchers(Url.SITE_EVENTS_PAGE).hasAuthority(StringAuthority.VIEW_SITE_EVENTS)
.mvcMatchers(Url.SUGGEST_SERIES_COUNTRY).hasAuthority(StringAuthority.CREATE_SERIES)
.regexMatchers(HttpMethod.POST, "/series/[0-9]+")
.hasAnyAuthority(
StringAuthority.UPDATE_COLLECTION,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ public enum Features implements Feature {

@Label("View site events")
@EnabledByDefault
VIEW_SITE_EVENTS;
VIEW_SITE_EVENTS,

@Label("/series/add: show link with auto-suggestions")
@EnabledByDefault
INFO_COUNTRY_SERIES;

public boolean isActive() {
return FeatureContext.getFeatureManager().isActive(this);
Expand Down
21 changes: 20 additions & 1 deletion src/main/javascript/series/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// IMPORTANT:
// You have to update Url.RESOURCES_VERSION each time whenever you're modified this file!
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Обрати внимание на это сообщение.

//
function initPage() {
function initPage(suggestCountryUrl) {
$('#country').selectize();

$('.js-catalog-numbers').on('blur', function() {
Expand All @@ -21,4 +21,23 @@ function initPage() {
$('.js-with-tooltip').tooltip({
'placement': 'right'
});

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Посмотри в шапке этого файла и не забудь поправить константу в классе Url.

if (suggestCountryUrl == null) {
return;
}

$.get(suggestCountryUrl, function (slug) {
if (slug == null)
return;

var country = $("#guess_country");
country.show();
country.click(function() {
$(this).hide();

var select_country = $("#country").selectize();
var selectize = select_country[0].selectize;
selectize.setValue(slug);
});
});
}
18 changes: 18 additions & 0 deletions src/main/resources/liquibase/sql/test-add-series.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
--
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему этот файл еще тут?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Все еще актуально.

-- Auto-generated by Maven, based on values from src/main/resources/test/spring/test-data.properties
--

INSERT INTO series(id, quantity, perforated, country_id, created_at, created_by, updated_at, updated_by, category_id) VALUES
(2, 1, 1, 2, NOW() + 1, 1, NOW(), 4, 1);

INSERT INTO series(id, quantity, perforated, country_id, created_at, created_by, updated_at, updated_by, category_id) VALUES
(3, 1, 1, 2, NOW() + 2, 1, NOW(), 4, 1);

INSERT INTO series(id, quantity, perforated, country_id, created_at, created_by, updated_at, updated_by, category_id) VALUES
(4, 1, 1, 2, NOW() + 3, 1, NOW(), 4, 1);

INSERT INTO series(id, quantity, perforated, country_id, created_at, created_by, updated_at, updated_by, category_id) VALUES
(5, 1, 1, 2, NOW() + 4, 1, NOW(), 4, 1);

INSERT INTO series(id, quantity, perforated, country_id, created_at, created_by, updated_at, updated_by, category_id) VALUES
(6, 1, 1, 4, NOW() + 5, 1, NOW(), 4, 1);
1 change: 1 addition & 0 deletions src/main/resources/ru/mystamps/i18n/Messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ t_add_more_images_hint = Later you will be able to add additional images
t_not_chosen = Not chosen
t_create_category_hint = You can also <a tabindex="-1" href="{0}">add a new category</a>
t_create_country_hint = You can also <a tabindex="-1" href="{0}">add a new country</a>
t_guess_country = Guess a country

# series/info.html
t_series_info = Info about series
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ t_add_more_images_hint = Вы сможете добавить дополните
t_not_chosen = Не выбрана
t_create_category_hint = Вы также можете <a tabindex="-1" href="{0}">добавить новую категорию</a>
t_create_country_hint = Вы также можете <a tabindex="-1" href="{0}">добавить новую страну</a>
t_guess_country = Угадать страну

# series/info.html
t_series_info = Информация о серии
Expand Down
14 changes: 14 additions & 0 deletions src/main/resources/sql/country_dao_queries.properties
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,17 @@ country.find_country_link_info_by_slug = \
FROM countries c \
WHERE c.slug = :slug \
ORDER BY CASE WHEN 'ru' = :lang THEN COALESCE(c.name_ru, c.name) ELSE c.name END

country.find_last_country_by_id = \
SELECT c.slug \
FROM series s \
LEFT JOIN countries c ON c.id = s.country_id \
WHERE s.created_by = :created_by \
ORDER BY s.created_at DESC LIMIT 1

country.find_popular_country = \
SELECT c.slug \
FROM series s \
LEFT JOIN countries c ON c.id = s.country_id \
GROUP BY country_id \
ORDER BY COUNT(*) DESC LIMIT 1
6 changes: 5 additions & 1 deletion src/main/webapp/WEB-INF/views/series/add.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<link rel="stylesheet" href="../../static/styles/main.css" th:href="${MAIN_CSS}" />
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.12.3/css/selectize.bootstrap3.min.css" th:href="${SELECTIZE_CSS}" />
</head>
<body onload="initPage()">
<body th:onload="|initPage('@{${SUGGEST_SERIES_COUNTRY}}')|" onload="initPage(null)">
<div class="container-fluid">
<div class="row" id="header">
<div id="logo" class="col-sm-9 vcenter">
Expand Down Expand Up @@ -202,6 +202,10 @@ <h3 th:text="${#strings.capitalize(add_series)}">
<span id="country.errors" class="help-block" th:if="${#fields.hasErrors('country')}" th:each="error : ${#fields.errors('country')}" th:text="${error}"></span>
/*/-->
</div>

<small togglz:active="INFO_COUNTRY_SERIES" id="guess_country" th:style="'display: none;'">
<a tabindex="-1" th:text="#{t_guess_country}" href="javascript:void(0)">Guess a country</a>
</small>
</div>

<div class="form-group form-group-sm" th:classappend="${#fields.hasErrors('quantity') ? 'has-error' : ''}">
Expand Down