Skip to content

Commit

Permalink
CLDR-17461 Forum posts in vetting view, boost performance, change icons
Browse files Browse the repository at this point in the history
-Add a cache localeForumStatusMap in SurveyForum.java

-New class SurveyForum.LocaleForumStatus

-Get all the status for a locale with a single sql call

-Clear the cache for a locale when a post is added/closed

-Revise icons in the Comparison (English) column: 👁️‍🗨️ and 💬

-👁️‍🗨️ means: This item has one or more forum posts, some of which are open

-💬 means: This item has one or more forum posts, all of which are closed

-Change let to const for two items in cldrSurvey.mjs; remove @Property

-TODO comment in cldrForum.mjs for updating table when a post is added/closed
  • Loading branch information
btangmu committed May 7, 2024
1 parent f9f77ba commit 4660154
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 33 deletions.
8 changes: 8 additions & 0 deletions tools/cldr-apps/js/src/esm/cldrForum.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,14 @@ function loadHandlerForSubmit(data) {
cldrLoad.reloadV(); // main Forum page
} else {
cldrForumPanel.updatePosts(null); // Info Panel
// TODO: refresh forum icons (👁️‍🗨️, 💬) in the main table
// Reference: https://unicode-org.atlassian.net/browse/CLDR-17461
// Calling expediteStatusUpdate does not have the desired effect, since
// the status response json.localeStamp only changes due to recent votes,
// not due to recent posts.
// cldrSurvey.expediteStatusUpdate(); // refresh forum icons in the main table
// console.log("cldrForum.loadHandlerForSubmit called expediteStatusUpdate");
// cldrTable.refreshSingleRow(...)
}
} else {
const post = $(".post").first();
Expand Down
5 changes: 2 additions & 3 deletions tools/cldr-apps/js/src/esm/cldrSurvey.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,9 @@ const statusActionTable = {
/**
* How often to fetch updates. Default 15s.
* Used only for delay in calling updateStatus.
* @property timerSpeed
*/
let timerSpeed = 15000; // 15 seconds
let fastTimerSpeed = 3000; // 3 seconds
const timerSpeed = 15000; // 15 seconds
const fastTimerSpeed = 3000; // 3 seconds
let statusTimeout = null;

let overridedir = null;
Expand Down
4 changes: 3 additions & 1 deletion tools/cldr-apps/js/src/esm/cldrTable.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,9 @@ function appendTranslationHintIcon(parent, text, loc) {

function appendForumStatus(parent, forumStatus, loc) {
const el = document.createElement("span");
el.textContent = "💬" + (forumStatus.hasOpenPosts ? "?" : ".");
el.textContent = forumStatus.hasOpenPosts
? cldrText.get("forum_path_has_open_posts_icon")
: cldrText.get("forum_path_has_only_closed_posts_icon");
el.title =
cldrText.get("forum_path_has_posts") +
(forumStatus.hasOpenPosts
Expand Down
4 changes: 3 additions & 1 deletion tools/cldr-apps/js/src/esm/cldrText.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,11 @@ const strings = {
forum_remember_vote:
"⚠️ Please remember to vote – submitting a forum post does NOT cause any actual vote to be made.",

forum_path_has_posts: "This item has forum posts, ",
forum_path_has_posts: "This item has one or more forum posts, ",
forum_path_has_open_posts: "some of which are open",
forum_path_has_only_closed_posts: "all of which are closed",
forum_path_has_open_posts_icon: "👁️‍🗨️",
forum_path_has_only_closed_posts_icon: "💬",

generic_nolocale: "No locale chosen.",
defaultContent_msg:
Expand Down
82 changes: 54 additions & 28 deletions tools/cldr-apps/src/main/java/org/unicode/cldr/web/SurveyForum.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
Expand Down Expand Up @@ -47,6 +48,9 @@ public class SurveyForum {

public static final String F_XPATH = "xpath";

private static final ConcurrentHashMap<CLDRLocale, LocaleForumStatus> localeForumStatusMap =
new ConcurrentHashMap<>();

/**
* Make an "html-safe" version of the given string
*
Expand Down Expand Up @@ -1058,6 +1062,7 @@ public void doForumAfterVote(
autoPostDecline(locale, user, xpathId, value);
autoPostClose(locale, user, xpathId, value);
}
localeForumStatusMap.remove(locale);
}

/**
Expand Down Expand Up @@ -1303,6 +1308,7 @@ private Integer doPostInternal(PostInfo postInfo) throws SurveyException {
}
CLDRLocale locale = postInfo.getLocale();
sm.getSTFactory().get(locale).nextStamp();
localeForumStatusMap.remove(locale);
return postId;
}

Expand Down Expand Up @@ -1633,44 +1639,64 @@ public static class PathForumStatus {
public boolean hasPosts, hasOpenPosts;

public PathForumStatus(CLDRLocale locale, String xpath) {
LocaleForumStatus lfs =
localeForumStatusMap.computeIfAbsent(locale, LocaleForumStatus::new);
if (lfs.pathsWithSomeOpenPosts.contains(xpath)) {
this.hasPosts = this.hasOpenPosts = true;
} else if (lfs.pathsWithOnlyClosedPosts.contains(xpath)) {
this.hasPosts = true;
this.hasOpenPosts = false;
} else {
this.hasPosts = this.hasOpenPosts = false;
}
}
}

public static class LocaleForumStatus {
Set<String> pathsWithSomeOpenPosts, pathsWithOnlyClosedPosts;

public LocaleForumStatus(CLDRLocale locale) {
this.pathsWithSomeOpenPosts = ConcurrentHashMap.newKeySet();
this.pathsWithOnlyClosedPosts = ConcurrentHashMap.newKeySet();

final String localeId = locale.getBaseName();
final String tableName = DBUtils.Table.FORUM_POSTS.toString();
final String query =
"SELECT xpath, MAX(is_open) FROM " + tableName + " WHERE loc=? GROUP BY xpath";
Connection conn = null;
PreparedStatement ps = null;
final String tableName = DBUtils.Table.FORUM_POSTS.toString();
final String localeId = locale.getBaseName();
final int xpathId = CookieSession.sm.xpt.getByXpath(xpath);
try {
conn = DBUtils.getInstance().getAConnection();
if (conn == null) {
return;
}
// Expect most paths have NO posts, so check first for ANY posts (open or not).
// "LIMIT 1" may improve performance; no need to distinguish 1 from larger numbers
ps =
DBUtils.prepareForwardReadOnly(
conn,
"SELECT ID FROM " + tableName + " WHERE loc=? and xpath=? LIMIT 1");
ps = DBUtils.prepareForwardReadOnly(conn, query);
ps.setString(1, localeId);
ps.setInt(2, xpathId);
if (DBUtils.sqlCount(ps) <= 0) { // sqlCount returns -1 (not 0) for none!
this.hasPosts = this.hasOpenPosts = false;
return;
ResultSet rs = ps.executeQuery();
while (rs.next()) {
int xp = rs.getInt(1);
if (xp <= 0) {
continue;
}
String xpath = CookieSession.sm.xpt.getById(xp);
if (xpath == null) {
continue;
}
int openCount = rs.getInt(2);
if (openCount > 0) {
this.pathsWithSomeOpenPosts.add(xpath);
} else {
this.pathsWithOnlyClosedPosts.add(xpath);
}
}
this.hasPosts = true;
// Check for OPEN posts
ps =
DBUtils.prepareForwardReadOnly(
conn,
"SELECT ID FROM "
+ tableName
+ " WHERE loc=? and xpath=? AND is_open=1 LIMIT 1");
ps.setString(1, localeId);
ps.setInt(2, xpathId);
this.hasOpenPosts = DBUtils.sqlCount(ps) > 0;
rs.close();
} catch (SQLException e) {
SurveyLog.logException(
logger,
e,
"PathForumStatus for " + tableName + " " + locale + ":" + xpathId);
String complaint =
"SurveyForum: Error getting status for locale "
+ localeId
+ " - "
+ DBUtils.unchainSqlException(e);
logger.severe(complaint);
} finally {
DBUtils.close(ps, conn);
}
Expand Down

0 comments on commit 4660154

Please sign in to comment.