From 91a32101872229e50676eb218ac6885205cfbbce Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Fri, 19 Jan 2024 22:41:13 +1100 Subject: [PATCH 01/21] Add typings for comments files --- Parlance/ClientApp/src/components/Button.js | 7 ----- Parlance/ClientApp/src/components/Button.tsx | 13 ++++++++ Parlance/ClientApp/src/components/Modal.tsx | 2 +- Parlance/ClientApp/src/interfaces/comments.ts | 20 ++++++++++++ .../Languages/Translation/Overview.js | 5 --- .../Languages/Translation/Overview.tsx | 7 +++++ .../Comments/CommentsModal.module.css | 4 +++ .../{CommentsModal.js => CommentsModal.tsx} | 19 +++++++++--- ...ThreadReplyArea.js => ThreadReplyArea.tsx} | 31 ++++++++++++++----- .../{ThreadView.js => ThreadView.tsx} | 25 ++++++++++----- 10 files changed, 102 insertions(+), 31 deletions(-) delete mode 100644 Parlance/ClientApp/src/components/Button.js create mode 100644 Parlance/ClientApp/src/components/Button.tsx create mode 100644 Parlance/ClientApp/src/interfaces/comments.ts delete mode 100644 Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.js create mode 100644 Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx rename Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/{CommentsModal.js => CommentsModal.tsx} (79%) rename Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/{ThreadReplyArea.js => ThreadReplyArea.tsx} (80%) rename Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/{ThreadView.js => ThreadView.tsx} (76%) diff --git a/Parlance/ClientApp/src/components/Button.js b/Parlance/ClientApp/src/components/Button.js deleted file mode 100644 index ae24b8c8..00000000 --- a/Parlance/ClientApp/src/components/Button.js +++ /dev/null @@ -1,7 +0,0 @@ -import Styles from "./Button.module.css"; - -export default function (props) { - return
- {props.children} -
-} \ No newline at end of file diff --git a/Parlance/ClientApp/src/components/Button.tsx b/Parlance/ClientApp/src/components/Button.tsx new file mode 100644 index 00000000..b4f8b81d --- /dev/null +++ b/Parlance/ClientApp/src/components/Button.tsx @@ -0,0 +1,13 @@ +import Styles from "./Button.module.css"; +import {HTMLAttributes, ReactNode} from "react"; + +interface ButtonProps extends HTMLAttributes { + disabled?: boolean + children: ReactNode +} + +export default function (props: ButtonProps) { + return
+ {props.children} +
+} \ No newline at end of file diff --git a/Parlance/ClientApp/src/components/Modal.tsx b/Parlance/ClientApp/src/components/Modal.tsx index 0458cc2d..1b3157b3 100644 --- a/Parlance/ClientApp/src/components/Modal.tsx +++ b/Parlance/ClientApp/src/components/Modal.tsx @@ -19,7 +19,7 @@ interface ModalExportProps { buttons?: ModalButton[] onButtonClick?: () => {} children?: ReactNode | TFunctionResult - onBackClicked?: () => {} + onBackClicked?: () => void heading?: string topComponent?: ReactNode } diff --git a/Parlance/ClientApp/src/interfaces/comments.ts b/Parlance/ClientApp/src/interfaces/comments.ts new file mode 100644 index 00000000..14baac94 --- /dev/null +++ b/Parlance/ClientApp/src/interfaces/comments.ts @@ -0,0 +1,20 @@ +export interface Thread { + id: string + title: string + isClosed: boolean + isFlagged: boolean + author: Author + headCommentBody: string +} + +export interface Comment { + text: string, + date: number, + author: Author, + event: string | null +} + +interface Author { + username: string + picture: string +} diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.js b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.js deleted file mode 100644 index c654a096..00000000 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.js +++ /dev/null @@ -1,5 +0,0 @@ -export default function Overview({data}) { - return
- -
-} \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx new file mode 100644 index 00000000..caaf3a14 --- /dev/null +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx @@ -0,0 +1,7 @@ +export default function Overview({data}: { + data: any +}) { + return
+ Overview +
+} \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css index 0c7aa5ca..abdbd856 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css @@ -43,4 +43,8 @@ .goButton { grid-area: goButton; +} + +.closed { + color: var(--foreground-disabled-color); } \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.js b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx similarity index 79% rename from Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.js rename to Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx index 2cdab6ac..73b8104a 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.js +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx @@ -8,9 +8,13 @@ import Styles from "./CommentsModal.module.css"; import Icon from "../../../../../../../components/Icon"; import ThreadView from "./ThreadView"; import ThreadReplyArea from "./ThreadReplyArea"; +import {Thread} from "../../../../../../../interfaces/comments"; -function ThreadItem({item, onCurrentThreadChanged}) { - return
onCurrentThreadChanged(item)}> +function ThreadItem({item, onCurrentThreadChanged}: { + item: Thread, + onCurrentThreadChanged: (thread: Thread) => void +}) { + return
onCurrentThreadChanged(item)}> {item.title}
{item.headCommentBody}
@@ -18,8 +22,15 @@ function ThreadItem({item, onCurrentThreadChanged}) {
} -export default function CommentsModal({project, subproject, language, tkey, threads, onUpdateThreads}) { - const [currentThread, setCurrentThread] = useState(); +export default function CommentsModal({project, subproject, language, tkey, threads, onUpdateThreads}: { + project: string, + subproject: string, + language: string, + tkey: string, + threads: Thread[], + onUpdateThreads: () => void +}) { + const [currentThread, setCurrentThread] = useState(); const {t} = useTranslation(); const goBack = () => { diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.js b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx similarity index 80% rename from Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.js rename to Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx index 783f381a..e317a0e8 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.js +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx @@ -5,6 +5,12 @@ import Button from "../../../../../../../components/Button"; import UserManager from "../../../../../../../helpers/UserManager"; import Fetch from "../../../../../../../helpers/Fetch"; import {useState} from "react"; +import {Comment, Thread} from "../../../../../../../interfaces/comments"; + +interface CloseResponse { + comments: Comment[], + thread: Thread +} export default function ThreadReplyArea({ project, @@ -14,7 +20,16 @@ export default function ThreadReplyArea({ thread, onReloadThreads, onCurrentThreadChanged, onThreadDataChanged - }) { + }: { + project?: string, + subproject?: string, + language?: string, + tkey?: string, + thread?: Thread, + onReloadThreads: () => void, + onCurrentThreadChanged: (thread: Thread | null) => void, + onThreadDataChanged?: (threadData: Comment[]) => void +}) { const [title, setTitle] = useState(""); const [body, setBody] = useState(""); const [error, setError] = useState(""); @@ -26,7 +41,7 @@ export default function ThreadReplyArea({ setError(""); if (threadId) { try { - onThreadDataChanged(await Fetch.post(`/api/comments/${thread.id}`, { + onThreadDataChanged!(await Fetch.post(`/api/comments/${thread.id}`, { body: body })); } catch { @@ -34,7 +49,7 @@ export default function ThreadReplyArea({ return; } } else { - let thread; + let thread: Thread | null; try { thread = await Fetch.post(`/api/comments/${project}/${subproject}/${language}/${tkey}`, { title: title, @@ -53,24 +68,26 @@ export default function ThreadReplyArea({ }; const toggleClosed = async () => { + if (!thread) return; + let comments, newThread; if (thread.isClosed) { try { - ({comments, thread: newThread} = await Fetch.delete(`/api/comments/${thread.id}/close`)); + ({comments, thread: newThread} = await Fetch.delete(`/api/comments/${thread.id}/close`)); } catch { setError(t("THREAD_REOPEN_FAILURE_PROMPT")) return; } } else { try { - ({comments, thread: newThread} = await Fetch.post(`/api/comments/${thread.id}/close`)); + ({comments, thread: newThread} = await Fetch.post(`/api/comments/${thread.id}/close`, null)); } catch { setError(t("THREAD_CLOSE_FAILURE_PROMPT")) return; } } - onThreadDataChanged(comments); + onThreadDataChanged!(comments); onReloadThreads(); onCurrentThreadChanged(newThread); } @@ -85,7 +102,7 @@ export default function ThreadReplyArea({
}
- {t("COMMENT_POSTING_AS_PROMPT", {user: UserManager.currentUser.username})} + {t("COMMENT_POSTING_AS_PROMPT", {user: UserManager.currentUser!.username})}
{threadId && <> diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.js b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx similarity index 76% rename from Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.js rename to Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx index 93d26cca..6fc61298 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.js +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx @@ -6,8 +6,11 @@ import ThreadReplyArea from "./ThreadReplyArea"; import Styles from "./ThreadView.module.css"; import moment from "moment"; import {useTranslation} from "react-i18next"; +import {Comment, Thread} from "../../../../../../../interfaces/comments"; -function ThreadComment({data}) { +function ThreadComment({data}: { + data: Comment +}) { return
} -function EventName({event}) { +function EventName({event}: { + event: string +}) { const {t} = useTranslation(); - const events = { + const events: {[key: string]: string} = { "closed": t("THREAD_CLOSED_ACTION"), "reopened": t("THREAD_REOPENED_ACTION") }; @@ -26,17 +31,23 @@ function EventName({event}) { return {events[event]}; } -function ThreadEvent({data}) { +function ThreadEvent({data}: { + data: Comment +}) { return
{data.author.username} {moment(data.date).fromNow()} + event={data.event!}/> {moment(data.date).fromNow()}
} -export default function ThreadView({thread, onCurrentThreadChanged, onReloadThreads}) { - const [threadData, setThreadData] = useState([]); +export default function ThreadView({thread, onCurrentThreadChanged, onReloadThreads}: { + thread: Thread, + onCurrentThreadChanged: (thread: Thread | null) => void, + onReloadThreads: () => void +}) { + const [threadData, setThreadData] = useState([]); const updateThreadData = async () => { setThreadData(await Fetch.get(`/api/comments/${thread.id}`)); From 9e0a9c7dc75c1ac35e13eba683fce382373a9608 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Sun, 21 Jan 2024 01:31:22 +1100 Subject: [PATCH 02/21] Extract comments into service --- Parlance/Controllers/CommentsController.cs | 38 +++++-------------- Parlance/Program.cs | 2 + Parlance/Services/Comments/CommentsService.cs | 37 ++++++++++++++++++ .../Services/Comments/ICommentsService.cs | 9 +++++ 4 files changed, 57 insertions(+), 29 deletions(-) create mode 100644 Parlance/Services/Comments/CommentsService.cs create mode 100644 Parlance/Services/Comments/ICommentsService.cs diff --git a/Parlance/Controllers/CommentsController.cs b/Parlance/Controllers/CommentsController.cs index 145cefba..e763b412 100644 --- a/Parlance/Controllers/CommentsController.cs +++ b/Parlance/Controllers/CommentsController.cs @@ -9,9 +9,9 @@ using Parlance.Helpers; using Parlance.Project; using Parlance.Project.Index; +using Parlance.Services.Comments; using Parlance.Services.Projects; using Parlance.Vicr123Accounts.Authentication; -using Parlance.Vicr123Accounts.Services; namespace Parlance.Controllers; @@ -20,18 +20,18 @@ namespace Parlance.Controllers; [EnableRateLimiting("limiter")] public class CommentsController : Controller { - private readonly IVicr123AccountsService _accountsService; + private readonly ICommentsService _commentsService; private readonly ParlanceContext _databaseContext; private readonly IParlanceIndexingService _indexingService; private readonly IProjectService _projectService; public CommentsController(ParlanceContext databaseContext, IProjectService projectService, - IParlanceIndexingService indexingService, IVicr123AccountsService accountsService) + IParlanceIndexingService indexingService, ICommentsService commentsService) { _databaseContext = databaseContext; _projectService = projectService; _indexingService = indexingService; - _accountsService = accountsService; + _commentsService = commentsService; } [HttpGet] @@ -60,7 +60,7 @@ public async Task GetCommentThreads(string project, string subpro foreach (var thread in threads) { var headComment = _databaseContext.Comments.Where(c => c.ThreadId == thread.Id && c.Event == null).OrderBy(c => c.Date).Last(); - result.Add(await GetJsonThread(thread, headComment)); + result.Add(await _commentsService.GetJsonThread(thread, headComment)); } return Json(result); @@ -123,7 +123,7 @@ public async Task CreateNewCommentThread(string project, string s await _databaseContext.SaveChangesAsync(); - return Json(await GetJsonThread(thread, headComment)); + return Json(await _commentsService.GetJsonThread(thread, headComment)); } [HttpGet] @@ -205,7 +205,7 @@ public async Task CloseThread(Guid threadId) return Json(new { - Thread = await GetJsonThread(thread, headComment), + Thread = await _commentsService.GetJsonThread(thread, headComment), Comments = await CommentsInThread(threadId) }); } @@ -249,7 +249,7 @@ public async Task ReopenThread(Guid threadId) return Json(new { - Thread = await GetJsonThread(thread, headComment), + Thread = await _commentsService.GetJsonThread(thread, headComment), Comments = await CommentsInThread(threadId) }); } @@ -259,26 +259,6 @@ public async Task ReopenThread(Guid threadId) } } - private async Task GetAuthor(ulong userId) - { - var user = await _accountsService.UserById(userId); - return new - { - user.Username, - Picture = - $"https://www.gravatar.com/avatar/{Convert.ToHexString(MD5.HashData(new UTF8Encoding(false).GetBytes(user.Email.Trim().ToLower()))).ToLower()}" - }; - } - - private async Task GetJsonThread(CommentThread thread, Comment headComment) - { - return new - { - thread.Id, thread.Title, thread.IsClosed, thread.IsFlagged, Author = await GetAuthor(headComment.UserId), - HeadCommentBody = headComment.Text - }; - } - private async Task?> CommentsInThread(Guid threadId) { var comments = new List(); @@ -293,7 +273,7 @@ private async Task GetJsonThread(CommentThread thread, Comment headComme { comments.Add(new { - comment.Text, comment.Date, Author = await GetAuthor(comment.UserId), comment.Event + comment.Text, comment.Date, Author = await _commentsService.GetAuthor(comment.UserId), comment.Event }); } diff --git a/Parlance/Program.cs b/Parlance/Program.cs index bb7ef20c..a823c850 100644 --- a/Parlance/Program.cs +++ b/Parlance/Program.cs @@ -13,6 +13,7 @@ using Parlance.Jobs; using Parlance.Project; using Parlance.RateLimiting; +using Parlance.Services.Comments; using Parlance.Services.Permissions; using Parlance.Services.ProjectMaintainers; using Parlance.Services.Projects; @@ -42,6 +43,7 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddHostedService(); diff --git a/Parlance/Services/Comments/CommentsService.cs b/Parlance/Services/Comments/CommentsService.cs new file mode 100644 index 00000000..d6528742 --- /dev/null +++ b/Parlance/Services/Comments/CommentsService.cs @@ -0,0 +1,37 @@ +using System.Security.Cryptography; +using System.Text; +using Parlance.Database.Models; +using Parlance.Vicr123Accounts.Services; + +namespace Parlance.Services.Comments; + +public class CommentsService : ICommentsService +{ + private readonly IVicr123AccountsService _accountsService; + + public CommentsService(IVicr123AccountsService accountsService) + { + _accountsService = accountsService; + } + + public async Task GetJsonThread(CommentThread thread, Comment headComment) + { + return new + { + thread.Id, thread.Title, thread.IsClosed, thread.IsFlagged, Author = await GetAuthor(headComment.UserId), + HeadCommentBody = headComment.Text + }; + } + + + public async Task GetAuthor(ulong userId) + { + var user = await _accountsService.UserById(userId); + return new + { + user.Username, + Picture = + $"https://www.gravatar.com/avatar/{Convert.ToHexString(MD5.HashData(new UTF8Encoding(false).GetBytes(user.Email.Trim().ToLower()))).ToLower()}" + }; + } +} \ No newline at end of file diff --git a/Parlance/Services/Comments/ICommentsService.cs b/Parlance/Services/Comments/ICommentsService.cs new file mode 100644 index 00000000..9e58c801 --- /dev/null +++ b/Parlance/Services/Comments/ICommentsService.cs @@ -0,0 +1,9 @@ +using Parlance.Database.Models; + +namespace Parlance.Services.Comments; + +public interface ICommentsService +{ + Task GetJsonThread(CommentThread thread, Comment headComment); + Task GetAuthor(ulong userId); +} \ No newline at end of file From e4fdb07d910ee29ffab2bc6e12ade04889d9355b Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Mon, 22 Jan 2024 21:54:48 +1100 Subject: [PATCH 03/21] Pull more methods into comments service --- Parlance/Controllers/CommentsController.cs | 7 ++-- Parlance/Parlance.csproj | 2 +- Parlance/Services/Comments/CommentsService.cs | 33 ++++++++++++++++++- .../Services/Comments/ICommentsService.cs | 3 ++ 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/Parlance/Controllers/CommentsController.cs b/Parlance/Controllers/CommentsController.cs index e763b412..842155de 100644 --- a/Parlance/Controllers/CommentsController.cs +++ b/Parlance/Controllers/CommentsController.cs @@ -53,13 +53,12 @@ public async Task GetCommentThreads(string project, string subpro return NotFound(); } - var threads = _databaseContext.CommentThreads.Where(x => - x.Project == project && x.Subproject == subproject && - x.Language == language.ToLocale().ToDatabaseRepresentation() && x.Key == key).ToList(); + var threads = _commentsService.Threads(project, subproject, language.ToLocale(), key); + var result = new List(); foreach (var thread in threads) { - var headComment = _databaseContext.Comments.Where(c => c.ThreadId == thread.Id && c.Event == null).OrderBy(c => c.Date).Last(); + var headComment = _commentsService.HeadComment(thread); result.Add(await _commentsService.GetJsonThread(thread, headComment)); } diff --git a/Parlance/Parlance.csproj b/Parlance/Parlance.csproj index 9b8156f6..b2bfbe17 100644 --- a/Parlance/Parlance.csproj +++ b/Parlance/Parlance.csproj @@ -73,6 +73,6 @@ - <_ContentIncludedByDefault Remove="ServiceReference\dotnet-svcutil.params.json" /> + \ No newline at end of file diff --git a/Parlance/Services/Comments/CommentsService.cs b/Parlance/Services/Comments/CommentsService.cs index d6528742..d5ffcc18 100644 --- a/Parlance/Services/Comments/CommentsService.cs +++ b/Parlance/Services/Comments/CommentsService.cs @@ -1,5 +1,7 @@ using System.Security.Cryptography; using System.Text; +using Parlance.CldrData; +using Parlance.Database; using Parlance.Database.Models; using Parlance.Vicr123Accounts.Services; @@ -8,10 +10,12 @@ namespace Parlance.Services.Comments; public class CommentsService : ICommentsService { private readonly IVicr123AccountsService _accountsService; + private readonly ParlanceContext _databaseContext; - public CommentsService(IVicr123AccountsService accountsService) + public CommentsService(IVicr123AccountsService accountsService, ParlanceContext databaseContext) { _accountsService = accountsService; + _databaseContext = databaseContext; } public async Task GetJsonThread(CommentThread thread, Comment headComment) @@ -34,4 +38,31 @@ public async Task GetAuthor(ulong userId) $"https://www.gravatar.com/avatar/{Convert.ToHexString(MD5.HashData(new UTF8Encoding(false).GetBytes(user.Email.Trim().ToLower()))).ToLower()}" }; } + + public IEnumerable Threads(string project = "", string subproject = "", Locale? language = null, string key = "", bool openOnly = false) + { + IQueryable query = _databaseContext.CommentThreads; + + if (!string.IsNullOrEmpty(project)) + query = query.Where(thread => thread.Project == project); + + if (!string.IsNullOrEmpty(subproject)) + query = query.Where(thread => thread.Subproject == subproject); + + if (language is not null) + query = query.Where(thread => thread.Language == language.ToDatabaseRepresentation()); + + if (!string.IsNullOrEmpty(key)) + query = query.Where(thread => thread.Key == key); + + if (openOnly) + query = query.Where(thread => !thread.IsClosed); + + return query; + } + + public Comment HeadComment(CommentThread thread) + { + return _databaseContext.Comments.Where(c => c.ThreadId == thread.Id && c.Event == null).OrderBy(c => c.Date).Last(); + } } \ No newline at end of file diff --git a/Parlance/Services/Comments/ICommentsService.cs b/Parlance/Services/Comments/ICommentsService.cs index 9e58c801..b59bce14 100644 --- a/Parlance/Services/Comments/ICommentsService.cs +++ b/Parlance/Services/Comments/ICommentsService.cs @@ -1,3 +1,4 @@ +using Parlance.CldrData; using Parlance.Database.Models; namespace Parlance.Services.Comments; @@ -6,4 +7,6 @@ public interface ICommentsService { Task GetJsonThread(CommentThread thread, Comment headComment); Task GetAuthor(ulong userId); + Comment HeadComment(CommentThread thread); + IEnumerable Threads(string project = "", string subproject = "", Locale? language = null, string key = "", bool openOnly = false); } \ No newline at end of file From 467a72ef27612b930d9d47d445dcc663b094d513 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Mon, 22 Jan 2024 22:28:54 +1100 Subject: [PATCH 04/21] Add open threads in meta API response --- Parlance/Controllers/CommentsController.cs | 9 +-------- Parlance/Controllers/ProjectsController.cs | 10 ++++++++-- Parlance/Services/Comments/CommentsService.cs | 18 +++++++++++++++++- Parlance/Services/Comments/ICommentsService.cs | 2 ++ 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Parlance/Controllers/CommentsController.cs b/Parlance/Controllers/CommentsController.cs index 842155de..865df4b5 100644 --- a/Parlance/Controllers/CommentsController.cs +++ b/Parlance/Controllers/CommentsController.cs @@ -55,14 +55,7 @@ public async Task GetCommentThreads(string project, string subpro var threads = _commentsService.Threads(project, subproject, language.ToLocale(), key); - var result = new List(); - foreach (var thread in threads) - { - var headComment = _commentsService.HeadComment(thread); - result.Add(await _commentsService.GetJsonThread(thread, headComment)); - } - - return Json(result); + return Json(await _commentsService.GetJsonThreads(threads)); } [HttpPost] diff --git a/Parlance/Controllers/ProjectsController.cs b/Parlance/Controllers/ProjectsController.cs index b79353c4..3cbe0bae 100644 --- a/Parlance/Controllers/ProjectsController.cs +++ b/Parlance/Controllers/ProjectsController.cs @@ -14,6 +14,7 @@ using Parlance.Project.Index; using Parlance.Project.SourceStrings; using Parlance.Project.TranslationFiles; +using Parlance.Services.Comments; using Parlance.Services.Permissions; using Parlance.Services.ProjectMaintainers; using Parlance.Services.Projects; @@ -35,6 +36,7 @@ public class ProjectsController : Controller private readonly IPermissionsService _permissionsService; private readonly IProjectMaintainersService _projectMaintainersService; private readonly IGlossaryService _glossaryService; + private readonly ICommentsService _commentsService; private readonly IProjectService _projectService; private readonly IParlanceSourceStringsService _sourceStringsService; @@ -42,7 +44,7 @@ public ProjectsController(IProjectService projectService, IPermissionsService permissionsService, IParlanceIndexingService indexingService, IParlanceSourceStringsService sourceStringsService, IPendingEditsService pendingEditsService, IVicr123AccountsService accountsService, - IProjectMaintainersService projectMaintainersService, IGlossaryService glossaryService) + IProjectMaintainersService projectMaintainersService, IGlossaryService glossaryService, ICommentsService commentsService) { _projectService = projectService; _permissionsService = permissionsService; @@ -52,6 +54,7 @@ public ProjectsController(IProjectService projectService, _accountsService = accountsService; _projectMaintainersService = projectMaintainersService; _glossaryService = glossaryService; + _commentsService = commentsService; } [HttpGet] @@ -475,13 +478,16 @@ public async Task GetProjectMeta(string project, string subprojec var username = HttpContext.User.Claims.FirstOrDefault(claim => claim.Type == Claims.Username)?.Value; + var openThreads = _commentsService.Threads(project, subproject, language.ToLocale(), openOnly: true); + return Json(new { CompletionData = indexResults, ProjectName = p.Name, SubprojectName = subp.Name, Language = subprojectLanguage.Locale.ToDashed(), - CanEdit = await _permissionsService.CanEditProjectLocale(username, project, language.ToLocale()) + CanEdit = await _permissionsService.CanEditProjectLocale(username, project, language.ToLocale()), + OpenThreads = await _commentsService.GetJsonThreads(openThreads) }); } catch (SubprojectNotFoundException) diff --git a/Parlance/Services/Comments/CommentsService.cs b/Parlance/Services/Comments/CommentsService.cs index d5ffcc18..02fb5a44 100644 --- a/Parlance/Services/Comments/CommentsService.cs +++ b/Parlance/Services/Comments/CommentsService.cs @@ -17,6 +17,12 @@ public CommentsService(IVicr123AccountsService accountsService, ParlanceContext _accountsService = accountsService; _databaseContext = databaseContext; } + + public async Task GetJsonThread(CommentThread thread) + { + var headComment = HeadComment(thread); + return await GetJsonThread(thread, headComment); + } public async Task GetJsonThread(CommentThread thread, Comment headComment) { @@ -26,7 +32,17 @@ public async Task GetJsonThread(CommentThread thread, Comment headCommen HeadCommentBody = headComment.Text }; } - + + public async Task GetJsonThreads(IEnumerable threads) + { + var result = new List(); + foreach (var thread in threads) + { + result.Add(await GetJsonThread(thread)); + } + + return result; + } public async Task GetAuthor(ulong userId) { diff --git a/Parlance/Services/Comments/ICommentsService.cs b/Parlance/Services/Comments/ICommentsService.cs index b59bce14..f4aad8f4 100644 --- a/Parlance/Services/Comments/ICommentsService.cs +++ b/Parlance/Services/Comments/ICommentsService.cs @@ -9,4 +9,6 @@ public interface ICommentsService Task GetAuthor(ulong userId); Comment HeadComment(CommentThread thread); IEnumerable Threads(string project = "", string subproject = "", Locale? language = null, string key = "", bool openOnly = false); + Task GetJsonThread(CommentThread thread); + Task GetJsonThreads(IEnumerable threads); } \ No newline at end of file From e729e7bf3a2fbc779d68b6803ad6c3e4a1ec1910 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 19:03:07 +1100 Subject: [PATCH 05/21] Add items in overview page --- .../translations/cs-CZ/translation.json | 2 ++ .../translations/da/translation.json | 2 ++ .../translations/de/translation.json | 2 ++ .../translations/en/translation.json | 2 ++ .../translations/es/translation.json | 2 ++ .../translations/fr-CA/translation.json | 2 ++ .../translations/he-IL/translation.json | 22 ++++++------ .../translations/nl/translation.json | 2 ++ .../translations/pt-BR/translation.json | 2 ++ .../translations/ro-RO/translation.json | 10 +++--- .../translations/uk/translation.json | 2 ++ .../translations/vi/translation.json | 4 ++- .../components/{ListPage.js => ListPage.tsx} | 20 ++++++++--- Parlance/ClientApp/src/interfaces/projects.ts | 20 +++++++++++ .../Translation/CommentsDashboard.tsx | 18 ++++++++++ .../{Dashboard.js => Dashboard.tsx} | 16 ++++++--- .../Languages/Translation/Overview.module.css | 0 .../Languages/Translation/Overview.tsx | 35 +++++++++++++++++-- 18 files changed, 137 insertions(+), 26 deletions(-) rename Parlance/ClientApp/src/components/{ListPage.js => ListPage.tsx} (73%) create mode 100644 Parlance/ClientApp/src/interfaces/projects.ts create mode 100644 Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx rename Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/{Dashboard.js => Dashboard.tsx} (75%) create mode 100644 Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.module.css diff --git a/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json b/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json index ae69e57b..c8761679 100644 --- a/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json +++ b/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", "PARLANCE_ADMINISTRATION_DESCRIPTION": "", "PARLANCE_ON_GIT": "", diff --git a/Parlance/ClientApp/public/resources/translations/da/translation.json b/Parlance/ClientApp/public/resources/translations/da/translation.json index 2924ca45..25b36209 100644 --- a/Parlance/ClientApp/public/resources/translations/da/translation.json +++ b/Parlance/ClientApp/public/resources/translations/da/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", "PARLANCE_ADMINISTRATION_DESCRIPTION": "", "PARLANCE_ON_GIT": "", diff --git a/Parlance/ClientApp/public/resources/translations/de/translation.json b/Parlance/ClientApp/public/resources/translations/de/translation.json index 034e62b3..c57e237f 100644 --- a/Parlance/ClientApp/public/resources/translations/de/translation.json +++ b/Parlance/ClientApp/public/resources/translations/de/translation.json @@ -177,6 +177,8 @@ "OK": "Ok", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Parlance Administration", "PARLANCE_ADMINISTRATION_DESCRIPTION": "Konfiguriere den Parlance server", "PARLANCE_ON_GIT": "", diff --git a/Parlance/ClientApp/public/resources/translations/en/translation.json b/Parlance/ClientApp/public/resources/translations/en/translation.json index 957e6f00..9b57cb85 100644 --- a/Parlance/ClientApp/public/resources/translations/en/translation.json +++ b/Parlance/ClientApp/public/resources/translations/en/translation.json @@ -180,6 +180,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Other Languages", "OVERVIEW": "Overview", + "OVERVIEW_GO_TO_COMMENTS": "Go to comments", + "OVERVIEW_STATS": "Stats", "PARLANCE_ADMINISTRATION": "Parlance Administration", "PARLANCE_ADMINISTRATION_DESCRIPTION": "Configure the Parlance server", "PARLANCE_ON_GIT": "Parlance on Git", diff --git a/Parlance/ClientApp/public/resources/translations/es/translation.json b/Parlance/ClientApp/public/resources/translations/es/translation.json index e6feca45..028cf65f 100644 --- a/Parlance/ClientApp/public/resources/translations/es/translation.json +++ b/Parlance/ClientApp/public/resources/translations/es/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", "PARLANCE_ADMINISTRATION_DESCRIPTION": "", "PARLANCE_ON_GIT": "", diff --git a/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json b/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json index 5f1ed5f3..eac96c58 100644 --- a/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json +++ b/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json @@ -178,6 +178,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", "PARLANCE_ADMINISTRATION_DESCRIPTION": "", "PARLANCE_ON_GIT": "", diff --git a/Parlance/ClientApp/public/resources/translations/he-IL/translation.json b/Parlance/ClientApp/public/resources/translations/he-IL/translation.json index 1e52bb5b..4bb10c82 100644 --- a/Parlance/ClientApp/public/resources/translations/he-IL/translation.json +++ b/Parlance/ClientApp/public/resources/translations/he-IL/translation.json @@ -31,16 +31,16 @@ "ACTIONS": "פעולות", "ADD_ENTRY_TO_GLOSSARY": "הוסף ערך למילון", "ADD_GLOSSARY": "הוסף מילון", - "ADD_GLOSSARY_CONNECT_PROJECT_PROMPT": "חבר מילון לפרויקט על ידי ביקור בפרויקט ובחירה ב-\u0022ניהול מילונים\u0022", + "ADD_GLOSSARY_CONNECT_PROJECT_PROMPT": "חבר מילון לפרויקט על ידי ביקור בפרויקט ובחירה ב-\"ניהול מילונים\"", "ADD_GLOSSARY_ERROR": "לא ניתן להוסיף מילון", "ADD_GLOSSARY_PROJECTS_CONNECTED_one": "פרויקט {{count}} מחובר", - "ADD_GLOSSARY_PROJECTS_CONNECTED_two": "{{count}} פרוייקטים מחוברים", "ADD_GLOSSARY_PROJECTS_CONNECTED_other": "{{count}} פרויקטים מחוברים", + "ADD_GLOSSARY_PROJECTS_CONNECTED_two": "{{count}} פרוייקטים מחוברים", "ADD_PROJECT": "הוסף פרויקט חדש", "ADD_PROJECT_ERROR": "לא ניתן להוסיף פרויקט חדש", "ADD_PROJECT_ERROR_PROMPT": "לא ניתן להוסיף את הפרויקט. נסה שוב במועד מאוחר יותר.", "ADD_PROJECT_PROMPT_1": "הזן את הנתונים הדרושים כדי להוסיף פרויקט", - "ADD_PROJECT_PROMPT_2": "ודא שהפרויקט מכיל קובץ \u003C1\u003E.parlance.json\u003C/1\u003E בשורש תיקיית הפרויקט.", + "ADD_PROJECT_PROMPT_2": "ודא שהפרויקט מכיל קובץ <1>.parlance.json בשורש תיקיית הפרויקט.", "ADD_TO_GLOSSARY": "הוסף למילון", "ADD_TO_GLOSSARY_CONFIRM": "הוסף ל-{{glossary}}", "ADD_TO_GLOSSARY_ERROR_NO_TERM": "הזן את המונח להוספה למילון", @@ -85,8 +85,8 @@ "COMMENTS": "תגובות", "COMMENT_ADD": "הוסף תגובה", "COMMENT_OPEN_THREADS_one": "פתוח שרשור תגובות {{count}}", - "COMMENT_OPEN_THREADS_two": "פתוחים {{count}} שרשורי תגובות", "COMMENT_OPEN_THREADS_other": "פתוחים {{count}} שרשורי תגובות", + "COMMENT_OPEN_THREADS_two": "פתוחים {{count}} שרשורי תגובות", "COMMENT_POST": "פרסם תגובה", "COMMENT_POSTING_AS_PROMPT": "מפרסם כ-{{user}}", "COMMENT_SEND_FAILURE_PROMPT": "לא ניתן לפרסם תגובה", @@ -129,7 +129,7 @@ "ERROR_TWO_FACTOR_IS_DISABLED": "אימות דו-גורמי מושבת.", "ERROR_UNKNOWN_USER": "המשתמש הזה אינו קיים.", "ERROR_USERNAME_ALREADY_EXISTS": "מצטערים, שם המשתמש הזה כבר תפוס.", - "ET_CETERA": "וכו\u0027", + "ET_CETERA": "וכו'", "FILTER_ALERT_STRINGS": "הצג מחרוזות עם התראות", "FILTER_ALL_STRINGS": "הצג כל המחרוזות", "FILTER_UNFINISHED_STRINGS": "הצג מחרוזות לא גמורות", @@ -182,6 +182,8 @@ "OK": "אישור", "OTHER_LANGUAGES": "שפות אחרות", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "ניהול Parlance", "PARLANCE_ADMINISTRATION_DESCRIPTION": "הגדר את שרת ה-Parlance", "PARLANCE_ON_GIT": "Parlance ב-Git", @@ -338,36 +340,36 @@ "USER_PERMISSIONS_TITLE": "הרשאות עבור {{user}}", "VCS_COMMIT": "בצע קומיט", "VCS_COMMIT_PROMPT_one": "בצע שינוי {{count}}?", - "VCS_COMMIT_PROMPT_two": "בצע {{count}} שינויים?", "VCS_COMMIT_PROMPT_other": "בצע {{count}} שינויים?", + "VCS_COMMIT_PROMPT_two": "בצע {{count}} שינויים?", "VCS_CREATED_COMMIT": "נוצר קומיט", "VCS_CREATED_COMMIT_PROMPT": "הקומיט נוצר", "VCS_CREATE_COMMIT": "צור קומיט", "VCS_DISCARD": "היפטר", "VCS_DISCARD_UNCOMMITTED_CHANGES": "היפטר משינויים להם לא בוצע קומיט", "VCS_DISCARD_UNCOMMITTED_CHANGES_PROMPT_one": "היפטר משינויים בהם לא בוצע קומיט בקובץ {{count}}?", - "VCS_DISCARD_UNCOMMITTED_CHANGES_PROMPT_two": "היפטר משינויים בהם לא בוצע קומיט ב-{{count}} קבצים?", "VCS_DISCARD_UNCOMMITTED_CHANGES_PROMPT_other": "היפטר משינויים בהם לא בוצע קומיט ב-{{count}} קבצים?", + "VCS_DISCARD_UNCOMMITTED_CHANGES_PROMPT_two": "היפטר משינויים בהם לא בוצע קומיט ב-{{count}} קבצים?", "VCS_FETCH": "השג", "VCS_GIT": "Git", "VCS_INCOMING_COMMITS": "קומיטים נכנסים", "VCS_INCOMING_COMMITS_PULL_one": "משוך קומיט {{count}}", - "VCS_INCOMING_COMMITS_PULL_two": "משוך {{count}} קומיטים", "VCS_INCOMING_COMMITS_PULL_other": "משוך {{count}} קומיטים", + "VCS_INCOMING_COMMITS_PULL_two": "משוך {{count}} קומיטים", "VCS_LAST_LOCAL_COMMIT": "קומיט מקומי אחרון", "VCS_LAST_REMOTE_COMMIT": "קומיט מכוון אחרון", "VCS_NOTHING_TO_COMMIT": "אין למה לבצע קומיט", "VCS_NOTHING_TO_COMMIT_PROMPT": "אין למה לבצע קומיט.", "VCS_OUTGOING_COMMITS": "קומיטים יוצאים", "VCS_OUTGOING_COMMITS_PUSH_one": "דחוף קומיט {{count}}", - "VCS_OUTGOING_COMMITS_PUSH_two": "דחוף {{count}} קומיטים", "VCS_OUTGOING_COMMITS_PUSH_other": "דחוף {{count}} קומיטים", + "VCS_OUTGOING_COMMITS_PUSH_two": "דחוף {{count}} קומיטים", "VCS_PULL": "משיכה", "VCS_PUSH": "דחיפה", "VCS_UNCOMMITTED_CHANGES": "שינויים שלא התבצעו", "VCS_UNCOMMITTED_CHANGES_COMMIT_one": "בצע קומיט לקובץ {{count}}", - "VCS_UNCOMMITTED_CHANGES_COMMIT_two": "בצע קומיטים ל-{{count}} קבצים", "VCS_UNCOMMITTED_CHANGES_COMMIT_other": "בצע קומיטים ל-{{count}} קבצים", + "VCS_UNCOMMITTED_CHANGES_COMMIT_two": "בצע קומיטים ל-{{count}} קבצים", "VERIFICATION_EMAIL_RESEND_PROMPT": "בדוק את דואר האלקטרוני שלך בשביל קוד אימות. ייתכן שתצטרך לבדוק את תיקיית הספאם שלך.", "VERIFY_EMAIL": "אמת דואר אלקטרוני", "VERIFY_EMAIL_FAILED_1": "אימות דואר האלקטרוני נכשל", diff --git a/Parlance/ClientApp/public/resources/translations/nl/translation.json b/Parlance/ClientApp/public/resources/translations/nl/translation.json index b6fee163..df33b9aa 100644 --- a/Parlance/ClientApp/public/resources/translations/nl/translation.json +++ b/Parlance/ClientApp/public/resources/translations/nl/translation.json @@ -178,6 +178,8 @@ "OK": "Oké", "OTHER_LANGUAGES": "Andere Talen", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Parlance-administratie", "PARLANCE_ADMINISTRATION_DESCRIPTION": "Parlance-server configureren", "PARLANCE_ON_GIT": "Parlance op Git", diff --git a/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json b/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json index 784b9384..7b22464c 100644 --- a/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json +++ b/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json @@ -177,6 +177,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Outras linguagens", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Administração de Parlance", "PARLANCE_ADMINISTRATION_DESCRIPTION": "Configurar servidor de Parlance", "PARLANCE_ON_GIT": "Parlance em Git", diff --git a/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json b/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json index fba46840..d7392ab4 100644 --- a/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json +++ b/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json @@ -37,7 +37,7 @@ "ADD_PROJECT_ERROR": "Nu am putut adăuga proiectul", "ADD_PROJECT_ERROR_PROMPT": "Nu am putut adăuga proiectul. Încearcă mai târziu.", "ADD_PROJECT_PROMPT_1": "Introdu datele necesare pentru a adăuga un proiect", - "ADD_PROJECT_PROMPT_2": "Asigură-te că proiectul conține un fișier \u003C1\u003E.parlance.json\u003C/1\u003E la rădăcină.", + "ADD_PROJECT_PROMPT_2": "Asigură-te că proiectul conține un fișier <1>.parlance.json la rădăcină.", "ADD_TO_GLOSSARY": "", "ADD_TO_GLOSSARY_CONFIRM": "", "ADD_TO_GLOSSARY_ERROR_NO_TERM": "", @@ -179,6 +179,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Alte limbi", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Administrație Parlance", "PARLANCE_ADMINISTRATION_DESCRIPTION": "Configură serverul Parlance", "PARLANCE_ON_GIT": "Parlance pe Git", @@ -235,7 +237,7 @@ "SECURITY_KEY_ADD_NAME_PROMPT": "Numele cheii de securitate", "SECURITY_KEY_ADD_PROMPT": "Urmărește instrucțiunile din browser pentru a adăuga o cheie de securitate.", "SECURITY_KEY_ADVERTISEMENT": "Poți să te conectezi mai rapid cu o cheie de acces. Cheile de acces pot fi setate rapid, și sunt mai sigure ca parolele.", - "SECURITY_KEY_ADVERTISEMENT_2": "Dacă nu vrei să setezi o cheie de acces chiar acum, poți mereu să vizitezi \u0022Setări chei de acces\u0022 în setările contului tău pentru a seta una.", + "SECURITY_KEY_ADVERTISEMENT_2": "Dacă nu vrei să setezi o cheie de acces chiar acum, poți mereu să vizitezi \"Setări chei de acces\" în setările contului tău pentru a seta una.", "SECURITY_KEY_ADVERTISEMENT_FEATURE_1_CONTENT": "Setarea poate fi efectuată în 10 secunde.", "SECURITY_KEY_ADVERTISEMENT_FEATURE_1_HEADING": "Setare rapidă", "SECURITY_KEY_ADVERTISEMENT_FEATURE_2_CONTENT": "Nu poți să îți uiți cheia de acces pentru că nu există nimic de ținut minte!", @@ -249,8 +251,8 @@ "SECURITY_KEY_ADVERTISEMENT_NEVER": "Nu pe acest dispozitiv", "SECURITY_KEY_ADVERTISEMENT_OK": "Setează acum", "SECURITY_KEY_ADVERTISEMENT_SETUP_SUCCESS": "Cheia de acces a fost înregistrată cu succes pe acest cont", - "SECURITY_KEY_ADVERTISEMENT_SETUP_SUCCESS_2": "Data viitoare când te conectezi la Parlance, poți folosi această cheie de acces introducându-ți numele de utilizator și selectând \u0022Folosește o cheie de acces\u0022 când ți se cere parola.", - "SECURITY_KEY_ADVERTISEMENT_SETUP_SUCCESS_3": "Pentru a-ți gestiona cheile de acces, poți să vizitezi setările contului tău și să selectezi \u0022Gestionare chei de acces\u0022.", + "SECURITY_KEY_ADVERTISEMENT_SETUP_SUCCESS_2": "Data viitoare când te conectezi la Parlance, poți folosi această cheie de acces introducându-ți numele de utilizator și selectând \"Folosește o cheie de acces\" când ți se cere parola.", + "SECURITY_KEY_ADVERTISEMENT_SETUP_SUCCESS_3": "Pentru a-ți gestiona cheile de acces, poți să vizitezi setările contului tău și să selectezi \"Gestionare chei de acces\".", "SECURITY_KEY_ADVERTISEMENT_SETUP_SUCCESS_TITLE": "Cheie de acces setată cu succes", "SECURITY_KEY_ADVERTISEMENT_TITLE": "Setare cheie de acces", "SECURITY_KEY_DEREGISTER": "Anulează cheia de securitate", diff --git a/Parlance/ClientApp/public/resources/translations/uk/translation.json b/Parlance/ClientApp/public/resources/translations/uk/translation.json index 0bd48b94..7851bfff 100644 --- a/Parlance/ClientApp/public/resources/translations/uk/translation.json +++ b/Parlance/ClientApp/public/resources/translations/uk/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", "PARLANCE_ADMINISTRATION_DESCRIPTION": "", "PARLANCE_ON_GIT": "", diff --git a/Parlance/ClientApp/public/resources/translations/vi/translation.json b/Parlance/ClientApp/public/resources/translations/vi/translation.json index 90e81ba2..c540d376 100644 --- a/Parlance/ClientApp/public/resources/translations/vi/translation.json +++ b/Parlance/ClientApp/public/resources/translations/vi/translation.json @@ -38,7 +38,7 @@ "ADD_PROJECT_ERROR": "Không thể thêm dự án", "ADD_PROJECT_ERROR_PROMPT": "", "ADD_PROJECT_PROMPT_1": "Điền vào dữ liệu để thêm dự án", - "ADD_PROJECT_PROMPT_2": "Đảm bảo rằng dự án này có tệp \u003C1\u003E.parlance.json\u003C/1\u003E trong thư mục góc", + "ADD_PROJECT_PROMPT_2": "Đảm bảo rằng dự án này có tệp <1>.parlance.json trong thư mục góc", "ADD_TO_GLOSSARY": "Thêm vào bảng chữ giải", "ADD_TO_GLOSSARY_CONFIRM": "Thêm vào {{glossary}}", "ADD_TO_GLOSSARY_ERROR_NO_TERM": "", @@ -178,6 +178,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Ngôn ngữ khác", "OVERVIEW": "", + "OVERVIEW_GO_TO_COMMENTS": "", + "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Quản lý Parlance", "PARLANCE_ADMINISTRATION_DESCRIPTION": "Cấu hình máy chủ Parlance", "PARLANCE_ON_GIT": "Parlance trên Git", diff --git a/Parlance/ClientApp/src/components/ListPage.js b/Parlance/ClientApp/src/components/ListPage.tsx similarity index 73% rename from Parlance/ClientApp/src/components/ListPage.js rename to Parlance/ClientApp/src/components/ListPage.tsx index 808fbbd9..868d0348 100644 --- a/Parlance/ClientApp/src/components/ListPage.js +++ b/Parlance/ClientApp/src/components/ListPage.tsx @@ -1,11 +1,21 @@ import Styles from "./ListPage.module.css"; import {Route, Routes, useLocation, useNavigate} from "react-router-dom"; +import {ReactNode} from "react"; -function toUrl(name) { +interface ListPageItemObject { + name: string, + render: ReactNode +} + +type ListPageItem = ListPageItemObject | string; + +function toUrl(name: string) { return name.toLowerCase().replace(" ", "-") } -function ListItem(props) { +function ListItem(props: { + name: string +}) { const navigate = useNavigate(); const location = useLocation(); @@ -23,7 +33,9 @@ function ListItem(props) { } -export default function ListPage({items}) { +export default function ListPage({items}: { + items: ListPageItem[] +}) { return
{items.map((item, i) => { @@ -36,7 +48,7 @@ export default function ListPage({items}) {
- {items.filter(item => typeof (item) === "object").map((item, index) => { + {(items.filter(item => typeof (item) === "object") as ListPageItemObject[]).map((item, index) => { return })} diff --git a/Parlance/ClientApp/src/interfaces/projects.ts b/Parlance/ClientApp/src/interfaces/projects.ts new file mode 100644 index 00000000..d77c05ce --- /dev/null +++ b/Parlance/ClientApp/src/interfaces/projects.ts @@ -0,0 +1,20 @@ +import {Thread} from "./comments"; + +export interface SubprojectLocaleMeta { + completionData: CompletionData + projectName: string, + subprojectName: string, + language: string, + canEdit: boolean, + openThreads: Thread[] +} + +export interface CompletionData { + count: number, + complete: number, + warnings: number, + errors: number, + cumulativeWarnings: number, + passedChecks: number, + needsAttention: number +} \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx new file mode 100644 index 00000000..d8a545c7 --- /dev/null +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx @@ -0,0 +1,18 @@ +import ListPageBlock from "../../../../../components/ListPageBlock"; +import {VerticalLayout} from "../../../../../components/Layouts"; +import PageHeading from "../../../../../components/PageHeading"; +import {useTranslation} from "react-i18next"; +import SelectableList from "../../../../../components/SelectableList"; + +export function CommentsDashboard() { + const {t} = useTranslation(); + + return
+ + + {t("COMMENTS")} + + + +
+} diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.js b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx similarity index 75% rename from Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.js rename to Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx index a993ba4b..5ba6b5d9 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.js +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx @@ -9,10 +9,12 @@ import Hero from "../../../../../components/Hero"; import BackButton from "../../../../../components/BackButton"; import Spinner from "../../../../../components/Spinner"; import GlossariesDashboard from "./GlossariesDashboard"; +import {SubprojectLocaleMeta} from "../../../../../interfaces/projects"; +import {CommentsDashboard} from "./CommentsDashboard"; -export default function Dashboard(props) { +export default function Dashboard() { const {project, subproject, language} = useParams(); - const [data, setData] = useState(); + const [data, setData] = useState(); const navigate = useNavigate(); const {t} = useTranslation(); @@ -35,13 +37,17 @@ export default function Dashboard(props) { }, { name: t("GLOSSARIES"), - render: + render: + }, + { + name: t("COMMENTS"), + render: } ]; return
navigate("../..")}/> - navigate("translate") @@ -49,4 +55,4 @@ export default function Dashboard(props) { ]}/>
-} \ No newline at end of file +} diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.module.css b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.module.css new file mode 100644 index 00000000..e69de29b diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx index caaf3a14..6bbc4778 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Overview.tsx @@ -1,7 +1,38 @@ +import {SubprojectLocaleMeta} from "../../../../../interfaces/projects"; +import {VerticalLayout} from "../../../../../components/Layouts"; +import ListPageBlock from "../../../../../components/ListPageBlock"; +import PageHeading from "../../../../../components/PageHeading"; +import {useTranslation} from "react-i18next"; +import SelectableList from "../../../../../components/SelectableList"; +import {useNavigate} from "react-router-dom"; + export default function Overview({data}: { - data: any + data: SubprojectLocaleMeta }) { + const {t} = useTranslation(); + const navigate = useNavigate(); + + const goToComments = () => { + navigate("../comments"); + } + return
- Overview + + + {t("OVERVIEW_STATS")} +
+ {data.completionData.complete}/{data.completionData.count} strings translated +
+
{data.completionData.warnings} warnings
+
{data.completionData.errors} errors
+
+
+ + + {t("COMMENTS")} +
{t("COMMENT_OPEN_THREADS", { count: data.openThreads.length })}
+ {t("OVERVIEW_GO_TO_COMMENTS")} +
+
} \ No newline at end of file From 74d42ad0fcaca14489d47ee63ea32609d3ee3200 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 19:23:07 +1100 Subject: [PATCH 06/21] Add comments threads to dashboard --- .../components/comments/ThreadItem.module.css | 46 +++++++++++++++++++ .../src/components/comments/ThreadItem.tsx | 16 +++++++ Parlance/ClientApp/src/interfaces/comments.ts | 5 ++ .../Translation/CommentsDashboard.tsx | 17 ++++++- .../Comments/CommentsModal.module.css | 43 ----------------- .../Comments/CommentsModal.tsx | 12 +---- Parlance/Controllers/CommentsController.cs | 18 ++++++++ Parlance/Services/Comments/CommentsService.cs | 24 ++++++++-- 8 files changed, 123 insertions(+), 58 deletions(-) create mode 100644 Parlance/ClientApp/src/components/comments/ThreadItem.module.css create mode 100644 Parlance/ClientApp/src/components/comments/ThreadItem.tsx diff --git a/Parlance/ClientApp/src/components/comments/ThreadItem.module.css b/Parlance/ClientApp/src/components/comments/ThreadItem.module.css new file mode 100644 index 00000000..7176942c --- /dev/null +++ b/Parlance/ClientApp/src/components/comments/ThreadItem.module.css @@ -0,0 +1,46 @@ +.threadItem { + display: grid; + grid-template-columns: 1fr max-content; + grid-template-rows: 1fr 1fr 1fr; + gap: 0px 0px; + grid-template-areas: + "threadTitle goButton" + "lastMessage goButton" + "threadCreator goButton"; + align-items: center; + + padding: 9px; + cursor: default; +} + +.threadItem:hover { + background-color: var(--hover-color); +} + +.threadItem:active { + background-color: var(--active-color); +} + +.threadTitle { + grid-area: threadTitle; +} + +.closed { + color: var(--foreground-disabled-color); +} + +.goButton { + grid-area: goButton; +} + +.lastMessage { + grid-area: lastMessage; +} + +.threadCreator { + grid-area: threadCreator; +} + +.noPadding { + padding: 0; +} \ No newline at end of file diff --git a/Parlance/ClientApp/src/components/comments/ThreadItem.tsx b/Parlance/ClientApp/src/components/comments/ThreadItem.tsx new file mode 100644 index 00000000..61941705 --- /dev/null +++ b/Parlance/ClientApp/src/components/comments/ThreadItem.tsx @@ -0,0 +1,16 @@ +import {Thread} from "../../interfaces/comments"; +import Styles from "./ThreadItem.module.css"; +import Icon from "../Icon"; + +export function ThreadItem({item, onCurrentThreadChanged, noPadding}: { + item: Thread, + onCurrentThreadChanged: (thread: Thread) => void, + noPadding?: boolean +}) { + return
onCurrentThreadChanged(item)}> + {item.title} + +
{item.headCommentBody}
+
{item.author.username}
+
+} \ No newline at end of file diff --git a/Parlance/ClientApp/src/interfaces/comments.ts b/Parlance/ClientApp/src/interfaces/comments.ts index 14baac94..317f4771 100644 --- a/Parlance/ClientApp/src/interfaces/comments.ts +++ b/Parlance/ClientApp/src/interfaces/comments.ts @@ -5,6 +5,11 @@ export interface Thread { isFlagged: boolean author: Author headCommentBody: string + project: string + subproject: string + language: string + key: string + sourceTranslation?: string } export interface Comment { diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx index d8a545c7..dc003e75 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx @@ -3,15 +3,30 @@ import {VerticalLayout} from "../../../../../components/Layouts"; import PageHeading from "../../../../../components/PageHeading"; import {useTranslation} from "react-i18next"; import SelectableList from "../../../../../components/SelectableList"; +import {useEffect, useState} from "react"; +import {Thread} from "../../../../../interfaces/comments"; +import {useParams} from "react-router-dom"; +import Fetch from "../../../../../helpers/Fetch"; +import {ThreadItem} from "../../../../../components/comments/ThreadItem"; export function CommentsDashboard() { + const {project, subproject, language} = useParams(); const {t} = useTranslation(); + const [comments, setComments] = useState(); + + useEffect(() => { + (async () => { + setComments(await Fetch.get(`/api/comments/${project}/${subproject}/${language}`)); + })(); + }, []); return
{t("COMMENTS")} - + ({ + contents: {}}/> + })) : SelectableList.PreloadingText(3)} />
diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css index abdbd856..7087aec9 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.module.css @@ -5,46 +5,3 @@ .threadsContainer { border-bottom: 1px solid var(--border-color); } - -.threadItem { - display: grid; - grid-template-columns: 1fr max-content; - grid-template-rows: 1fr 1fr 1fr; - gap: 0px 0px; - grid-template-areas: - "threadTitle goButton" - "lastMessage goButton" - "threadCreator goButton"; - align-items: center; - - padding: 9px; - cursor: default; -} - -.threadItem:hover { - background-color: var(--hover-color); -} - -.threadItem:active { - background-color: var(--active-color); -} - -.threadTitle { - grid-area: threadTitle; -} - -.lastMessage { - grid-area: lastMessage; -} - -.threadCreator { - grid-area: threadCreator; -} - -.goButton { - grid-area: goButton; -} - -.closed { - color: var(--foreground-disabled-color); -} \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx index 73b8104a..74dba7ec 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx @@ -9,18 +9,8 @@ import Icon from "../../../../../../../components/Icon"; import ThreadView from "./ThreadView"; import ThreadReplyArea from "./ThreadReplyArea"; import {Thread} from "../../../../../../../interfaces/comments"; +import {ThreadItem} from "../../../../../../../components/comments/ThreadItem"; -function ThreadItem({item, onCurrentThreadChanged}: { - item: Thread, - onCurrentThreadChanged: (thread: Thread) => void -}) { - return
onCurrentThreadChanged(item)}> - {item.title} - -
{item.headCommentBody}
-
{item.author.username}
-
-} export default function CommentsModal({project, subproject, language, tkey, threads, onUpdateThreads}: { project: string, diff --git a/Parlance/Controllers/CommentsController.cs b/Parlance/Controllers/CommentsController.cs index 865df4b5..751fde5c 100644 --- a/Parlance/Controllers/CommentsController.cs +++ b/Parlance/Controllers/CommentsController.cs @@ -34,6 +34,24 @@ public CommentsController(ParlanceContext databaseContext, IProjectService proje _commentsService = commentsService; } + [HttpGet] + [Route("{project}/{subproject}/{language}")] + public async Task GetCommentThreads(string project, string subproject, string language) + { + var p = await _projectService.ProjectBySystemName(project); + var subprojectLanguage = p.GetParlanceProject().SubprojectBySystemName(subproject) + .Language(language.ToLocale()); + await using var translationFile = await subprojectLanguage.CreateTranslationFile(_indexingService); + if (translationFile is null) + { + return NotFound(); + } + + var threads = _commentsService.Threads(project, subproject, language.ToLocale(), openOnly: true); + + return Json(await _commentsService.GetJsonThreads(threads)); + } + [HttpGet] [Route("{project}/{subproject}/{language}/{key}")] public async Task GetCommentThreads(string project, string subproject, string language, diff --git a/Parlance/Services/Comments/CommentsService.cs b/Parlance/Services/Comments/CommentsService.cs index 02fb5a44..027c17d4 100644 --- a/Parlance/Services/Comments/CommentsService.cs +++ b/Parlance/Services/Comments/CommentsService.cs @@ -3,6 +3,9 @@ using Parlance.CldrData; using Parlance.Database; using Parlance.Database.Models; +using Parlance.Project; +using Parlance.Project.Index; +using Parlance.Services.Projects; using Parlance.Vicr123Accounts.Services; namespace Parlance.Services.Comments; @@ -11,11 +14,15 @@ public class CommentsService : ICommentsService { private readonly IVicr123AccountsService _accountsService; private readonly ParlanceContext _databaseContext; + private readonly IProjectService _projectService; + private readonly IParlanceIndexingService _indexingService; - public CommentsService(IVicr123AccountsService accountsService, ParlanceContext databaseContext) + public CommentsService(IVicr123AccountsService accountsService, ParlanceContext databaseContext, IProjectService projectService, IParlanceIndexingService indexingService) { _accountsService = accountsService; _databaseContext = databaseContext; + _projectService = projectService; + _indexingService = indexingService; } public async Task GetJsonThread(CommentThread thread) @@ -26,10 +33,21 @@ public async Task GetJsonThread(CommentThread thread) public async Task GetJsonThread(CommentThread thread, Comment headComment) { + var language = Locale.FromDatabaseRepresentation(thread.Language)!; + + var p = await _projectService.ProjectBySystemName(thread.Project); + var subprojectLanguage = p.GetParlanceProject().SubprojectBySystemName(thread.Subproject) + .Language(language); + await using var translationFile = await subprojectLanguage.CreateTranslationFile(_indexingService); + + var entry = translationFile?.Entries.FirstOrDefault(x => x.Key == thread.Key); + return new { - thread.Id, thread.Title, thread.IsClosed, thread.IsFlagged, Author = await GetAuthor(headComment.UserId), - HeadCommentBody = headComment.Text + thread.Id, thread.Title, thread.IsClosed, thread.IsFlagged, thread.Project, thread.Subproject, + Language = language.ToDashed(), thread.Key, Author = await GetAuthor(headComment.UserId), + HeadCommentBody = headComment.Text, + SourceTranslation = entry?.Source }; } From c274c7b9b018dc04fef4a9db4abe5f39e5baa531 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 19:31:18 +1100 Subject: [PATCH 07/21] Add error message for no open threads --- .../resources/translations/cs-CZ/translation.json | 2 ++ .../resources/translations/da/translation.json | 2 ++ .../resources/translations/de/translation.json | 2 ++ .../resources/translations/en/translation.json | 2 ++ .../resources/translations/es/translation.json | 2 ++ .../resources/translations/fr-CA/translation.json | 2 ++ .../resources/translations/he-IL/translation.json | 2 ++ .../resources/translations/nl/translation.json | 2 ++ .../resources/translations/pt-BR/translation.json | 2 ++ .../resources/translations/ro-RO/translation.json | 2 ++ .../resources/translations/uk/translation.json | 2 ++ .../resources/translations/vi/translation.json | 2 ++ .../Languages/Translation/CommentsDashboard.tsx | 15 ++++++++++++--- 13 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json b/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json index c8761679..289b1d10 100644 --- a/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json +++ b/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", diff --git a/Parlance/ClientApp/public/resources/translations/da/translation.json b/Parlance/ClientApp/public/resources/translations/da/translation.json index 25b36209..ff46cee3 100644 --- a/Parlance/ClientApp/public/resources/translations/da/translation.json +++ b/Parlance/ClientApp/public/resources/translations/da/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", diff --git a/Parlance/ClientApp/public/resources/translations/de/translation.json b/Parlance/ClientApp/public/resources/translations/de/translation.json index c57e237f..2823fe54 100644 --- a/Parlance/ClientApp/public/resources/translations/de/translation.json +++ b/Parlance/ClientApp/public/resources/translations/de/translation.json @@ -177,6 +177,8 @@ "OK": "Ok", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Parlance Administration", diff --git a/Parlance/ClientApp/public/resources/translations/en/translation.json b/Parlance/ClientApp/public/resources/translations/en/translation.json index 9b57cb85..040937c8 100644 --- a/Parlance/ClientApp/public/resources/translations/en/translation.json +++ b/Parlance/ClientApp/public/resources/translations/en/translation.json @@ -180,6 +180,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Other Languages", "OVERVIEW": "Overview", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "No open threads", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "There are no open comment threads in this file right now", "OVERVIEW_GO_TO_COMMENTS": "Go to comments", "OVERVIEW_STATS": "Stats", "PARLANCE_ADMINISTRATION": "Parlance Administration", diff --git a/Parlance/ClientApp/public/resources/translations/es/translation.json b/Parlance/ClientApp/public/resources/translations/es/translation.json index 028cf65f..c835126d 100644 --- a/Parlance/ClientApp/public/resources/translations/es/translation.json +++ b/Parlance/ClientApp/public/resources/translations/es/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", diff --git a/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json b/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json index eac96c58..467fea61 100644 --- a/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json +++ b/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json @@ -178,6 +178,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", diff --git a/Parlance/ClientApp/public/resources/translations/he-IL/translation.json b/Parlance/ClientApp/public/resources/translations/he-IL/translation.json index 4bb10c82..d14d62bd 100644 --- a/Parlance/ClientApp/public/resources/translations/he-IL/translation.json +++ b/Parlance/ClientApp/public/resources/translations/he-IL/translation.json @@ -182,6 +182,8 @@ "OK": "אישור", "OTHER_LANGUAGES": "שפות אחרות", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "ניהול Parlance", diff --git a/Parlance/ClientApp/public/resources/translations/nl/translation.json b/Parlance/ClientApp/public/resources/translations/nl/translation.json index df33b9aa..ad4432bf 100644 --- a/Parlance/ClientApp/public/resources/translations/nl/translation.json +++ b/Parlance/ClientApp/public/resources/translations/nl/translation.json @@ -178,6 +178,8 @@ "OK": "Oké", "OTHER_LANGUAGES": "Andere Talen", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Parlance-administratie", diff --git a/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json b/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json index 7b22464c..bbd145bc 100644 --- a/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json +++ b/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json @@ -177,6 +177,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Outras linguagens", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Administração de Parlance", diff --git a/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json b/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json index d7392ab4..240584b4 100644 --- a/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json +++ b/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json @@ -179,6 +179,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Alte limbi", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Administrație Parlance", diff --git a/Parlance/ClientApp/public/resources/translations/uk/translation.json b/Parlance/ClientApp/public/resources/translations/uk/translation.json index 7851bfff..571cf104 100644 --- a/Parlance/ClientApp/public/resources/translations/uk/translation.json +++ b/Parlance/ClientApp/public/resources/translations/uk/translation.json @@ -177,6 +177,8 @@ "OK": "", "OTHER_LANGUAGES": "", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "", diff --git a/Parlance/ClientApp/public/resources/translations/vi/translation.json b/Parlance/ClientApp/public/resources/translations/vi/translation.json index c540d376..8f7a2ab0 100644 --- a/Parlance/ClientApp/public/resources/translations/vi/translation.json +++ b/Parlance/ClientApp/public/resources/translations/vi/translation.json @@ -178,6 +178,8 @@ "OK": "OK", "OTHER_LANGUAGES": "Ngôn ngữ khác", "OVERVIEW": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS": "", + "OVERVIEW_COMMENTS_NO_OPEN_THREADS_DESCRIPTION": "", "OVERVIEW_GO_TO_COMMENTS": "", "OVERVIEW_STATS": "", "PARLANCE_ADMINISTRATION": "Quản lý Parlance", diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx index dc003e75..bbb8ca00 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx @@ -8,6 +8,8 @@ import {Thread} from "../../../../../interfaces/comments"; import {useParams} from "react-router-dom"; import Fetch from "../../../../../helpers/Fetch"; import {ThreadItem} from "../../../../../components/comments/ThreadItem"; +import PreloadingBlock from "../../../../../components/PreloadingBlock"; +import SilentInformation from "../../../../../components/SilentInformation"; export function CommentsDashboard() { const {project, subproject, language} = useParams(); @@ -24,9 +26,16 @@ export function CommentsDashboard() { {t("COMMENTS")} - ({ - contents: {}}/> - })) : SelectableList.PreloadingText(3)} /> + {comments?.length === 0 ? +
+ +
: <> + {comments ?
{t("COMMENT_OPEN_THREADS", {count: comments.length})}
: {t("COMMENT_OPEN_THREADS", {count: 0})}} + ({ + contents: {}}/> + })) : SelectableList.PreloadingText(3)}/> + + }
From 6db3df991e9c42d92fb0840b65e11940dba28ca1 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 20:16:56 +1100 Subject: [PATCH 08/21] Add default route for overview --- Parlance/ClientApp/src/components/ListPage.tsx | 8 ++++++-- .../Subprojects/Languages/Translation/Dashboard.tsx | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Parlance/ClientApp/src/components/ListPage.tsx b/Parlance/ClientApp/src/components/ListPage.tsx index 868d0348..56367ddc 100644 --- a/Parlance/ClientApp/src/components/ListPage.tsx +++ b/Parlance/ClientApp/src/components/ListPage.tsx @@ -5,6 +5,7 @@ import {ReactNode} from "react"; interface ListPageItemObject { name: string, render: ReactNode + default?: boolean } type ListPageItem = ListPageItemObject | string; @@ -15,6 +16,7 @@ function toUrl(name: string) { function ListItem(props: { name: string + default?: boolean }) { const navigate = useNavigate(); const location = useLocation(); @@ -48,8 +50,10 @@ export default function ListPage({items}: {
- {(items.filter(item => typeof (item) === "object") as ListPageItemObject[]).map((item, index) => { - return + {(items.filter(item => typeof (item) === "object") as ListPageItemObject[]).flatMap((item, index) => { + const routes = [] + if (item.default) routes.push() + return routes; })}
diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx index 5ba6b5d9..94af63f5 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/Dashboard.tsx @@ -33,7 +33,8 @@ export default function Dashboard() { t("DASHBOARD"), { name: t("OVERVIEW"), - render: + render: , + default: true }, { name: t("GLOSSARIES"), From 94849cebad0f39891cb93be485eb08b456f534b9 Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 20:26:36 +1100 Subject: [PATCH 09/21] Add comment view to comments section --- .../Translation/CommentsDashboard.tsx | 20 ++++++++++++++----- .../Comments/CommentsModal.tsx | 13 ++++++++++-- .../TranslationEditor/TranslationArea.js | 2 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx index bbb8ca00..0abf41c5 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx @@ -10,18 +10,27 @@ import Fetch from "../../../../../helpers/Fetch"; import {ThreadItem} from "../../../../../components/comments/ThreadItem"; import PreloadingBlock from "../../../../../components/PreloadingBlock"; import SilentInformation from "../../../../../components/SilentInformation"; +import Modal from "../../../../../components/Modal"; +import {CommentsThreadModal} from "./TranslationEditor/Comments/CommentsModal"; export function CommentsDashboard() { const {project, subproject, language} = useParams(); const {t} = useTranslation(); - const [comments, setComments] = useState(); + const [comments, setComments] = useState(); + + const updateComments = async () => { + setComments(null); + setComments(await Fetch.get(`/api/comments/${project}/${subproject}/${language}`)); + } useEffect(() => { - (async () => { - setComments(await Fetch.get(`/api/comments/${project}/${subproject}/${language}`)); - })(); + void updateComments(); }, []); + const openThread = (thread: Thread) => { + Modal.mount() + } + return
@@ -32,7 +41,8 @@ export function CommentsDashboard() {
: <> {comments ?
{t("COMMENT_OPEN_THREADS", {count: comments.length})}
: {t("COMMENT_OPEN_THREADS", {count: 0})}} ({ - contents: {}}/> + contents: {}} />, + onClick: () => openThread(thread) })) : SelectableList.PreloadingText(3)}/> } diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx index 74dba7ec..6f56389e 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx @@ -12,13 +12,13 @@ import {Thread} from "../../../../../../../interfaces/comments"; import {ThreadItem} from "../../../../../../../components/comments/ThreadItem"; -export default function CommentsModal({project, subproject, language, tkey, threads, onUpdateThreads}: { +export function CommentsModal({project, subproject, language, tkey, threads, onUpdateThreads}: { project: string, subproject: string, language: string, tkey: string, threads: Thread[], - onUpdateThreads: () => void + onUpdateThreads: () => void, }) { const [currentThread, setCurrentThread] = useState(); const {t} = useTranslation(); @@ -51,4 +51,13 @@ export default function CommentsModal({project, subproject, language, tkey, thre } +} + +export function CommentsThreadModal({thread, onUpdateThreads}: { + thread: Thread + onUpdateThreads: () => void +}) { + return Modal.unmount()}> + {}} onReloadThreads={onUpdateThreads} /> + } \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/TranslationArea.js b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/TranslationArea.js index b4df9874..84ac6a59 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/TranslationArea.js +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/TranslationArea.js @@ -17,7 +17,7 @@ import Placeholders from "./Placeholders"; import {useForceUpdateOnUserChange} from "../../../../../../helpers/Hooks"; import Icon from "../../../../../../components/Icon"; import Modal from "../../../../../../components/Modal"; -import CommentsModal from "./Comments/CommentsModal"; +import { CommentsModal } from "./Comments/CommentsModal"; import Fetch from "../../../../../../helpers/Fetch"; import PreloadingBlock from "../../../../../../components/PreloadingBlock"; import GlossaryLookup from "./GlossaryLookup"; From c88a46c6d5e54c8c32f8851cde7c3a3f9eb3d57b Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 20:35:45 +1100 Subject: [PATCH 10/21] Add Level 4 Page Heading and Thread Header for Comments --- .../src/components/PageHeading.module.css | 7 ++++ .../ClientApp/src/components/PageHeading.tsx | 4 ++- .../Translation/CommentsDashboard.tsx | 2 +- .../Comments/CommentsModal.tsx | 7 ++-- .../Comments/ThreadView.module.css | 5 +++ .../TranslationEditor/Comments/ThreadView.tsx | 34 +++++++++++++++++-- 6 files changed, 51 insertions(+), 8 deletions(-) diff --git a/Parlance/ClientApp/src/components/PageHeading.module.css b/Parlance/ClientApp/src/components/PageHeading.module.css index deed3954..9a1fcfa3 100644 --- a/Parlance/ClientApp/src/components/PageHeading.module.css +++ b/Parlance/ClientApp/src/components/PageHeading.module.css @@ -13,4 +13,11 @@ font-weight: bold; text-transform: uppercase; margin: 0; +} + +.level4 { + font-size: 8pt; + font-weight: normal; + text-transform: uppercase; + margin: 0; } \ No newline at end of file diff --git a/Parlance/ClientApp/src/components/PageHeading.tsx b/Parlance/ClientApp/src/components/PageHeading.tsx index 7c700a7f..e71733bb 100644 --- a/Parlance/ClientApp/src/components/PageHeading.tsx +++ b/Parlance/ClientApp/src/components/PageHeading.tsx @@ -2,7 +2,7 @@ import Styles from "./PageHeading.module.css"; import {ReactElement, ReactNode} from "react"; interface PageHeadingProps { - level?: 1 | 2 | 3; + level?: 1 | 2 | 3 | 4; children: ReactNode; className?: string; } @@ -13,6 +13,8 @@ export default function PageHeading(props: PageHeadingProps): ReactElement { return

{props.children}

case 3: return

{props.children}

+ case 4: + return

{props.children}

default: return

{props.children}

} diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx index 0abf41c5..35c360f3 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/CommentsDashboard.tsx @@ -28,7 +28,7 @@ export function CommentsDashboard() { }, []); const openThread = (thread: Thread) => { - Modal.mount() + Modal.mount() } return
diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx index 6f56389e..22eeed17 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx @@ -53,11 +53,12 @@ export function CommentsModal({project, subproject, language, tkey, threads, onU } -export function CommentsThreadModal({thread, onUpdateThreads}: { +export function CommentsThreadModal({thread, onUpdateThreads, showHeader}: { thread: Thread - onUpdateThreads: () => void + onUpdateThreads: () => void, + showHeader?: boolean }) { return Modal.unmount()}> - {}} onReloadThreads={onUpdateThreads} /> + {}} onReloadThreads={onUpdateThreads} showHeader={showHeader} /> } \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.module.css b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.module.css index 6e2b81bc..678c038f 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.module.css +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.module.css @@ -50,3 +50,8 @@ border-bottom: 1px solid var(--border-color); } + +.headerItem { + padding: 9px; + border-bottom: 1px solid var(--border-color); +} \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx index 6fc61298..67a55f1c 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadView.tsx @@ -1,4 +1,4 @@ -import {VerticalLayout} from "../../../../../../../components/Layouts"; +import {HorizontalLayout, VerticalLayout} from "../../../../../../../components/Layouts"; import {useEffect, useState} from "react"; import Fetch from "../../../../../../../helpers/Fetch"; import ThreadReplyArea from "./ThreadReplyArea"; @@ -7,6 +7,11 @@ import Styles from "./ThreadView.module.css"; import moment from "moment"; import {useTranslation} from "react-i18next"; import {Comment, Thread} from "../../../../../../../interfaces/comments"; +import PageHeading from "../../../../../../../components/PageHeading"; +import SmallButton from "../../../../../../../components/SmallButton"; +import {ButtonGroup} from "reactstrap"; +import Modal from "../../../../../../../components/Modal"; +import {useNavigate} from "react-router-dom"; function ThreadComment({data}: { data: Comment @@ -42,10 +47,32 @@ function ThreadEvent({data}: {
} -export default function ThreadView({thread, onCurrentThreadChanged, onReloadThreads}: { +function ThreadHeader({thread}: { + thread: Thread +}) { + const {t} = useTranslation(); + + const goToString = () => { + Modal.unmount(); + window.location.pathname = `/projects/${thread.project}/${thread.subproject}/${thread.language}/translate/${thread.key}`; + } + + return
+ + {t("Original Translation")} +
{thread.sourceTranslation}
+ + {t("Go to string")} + +
+
+} + +export default function ThreadView({thread, onCurrentThreadChanged, onReloadThreads, showHeader}: { thread: Thread, onCurrentThreadChanged: (thread: Thread | null) => void, - onReloadThreads: () => void + onReloadThreads: () => void, + showHeader?: boolean }) { const [threadData, setThreadData] = useState([]); @@ -58,6 +85,7 @@ export default function ThreadView({thread, onCurrentThreadChanged, onReloadThre }, []); return + {showHeader && } {threadData.map((x, i) => x.event ? : )} From 4f48f63cbad48ffb28fadbf97e125438cf71398d Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 20:38:02 +1100 Subject: [PATCH 11/21] Add max-height property to Modal styles --- Parlance/ClientApp/src/components/Modal.module.css | 1 + 1 file changed, 1 insertion(+) diff --git a/Parlance/ClientApp/src/components/Modal.module.css b/Parlance/ClientApp/src/components/Modal.module.css index 4de7fa4c..5728c05e 100644 --- a/Parlance/ClientApp/src/components/Modal.module.css +++ b/Parlance/ClientApp/src/components/Modal.module.css @@ -26,6 +26,7 @@ border: 1px solid var(--border-color); flex-basis: 600px; + max-height: 100vh; } .PopoverContainer { From 02da83e1f34bb18f517198384a200064ef81012c Mon Sep 17 00:00:00 2001 From: Victor Tran Date: Tue, 23 Jan 2024 20:43:39 +1100 Subject: [PATCH 12/21] Add logged-in user check for thread commenting --- .../translations/cs-CZ/translation.json | 1 + .../translations/da/translation.json | 1 + .../translations/de/translation.json | 1 + .../translations/en/translation.json | 1 + .../translations/es/translation.json | 1 + .../translations/fr-CA/translation.json | 1 + .../translations/he-IL/translation.json | 1 + .../translations/nl/translation.json | 1 + .../translations/pt-BR/translation.json | 1 + .../translations/ro-RO/translation.json | 1 + .../translations/uk/translation.json | 1 + .../translations/vi/translation.json | 1 + .../Comments/CommentsModal.tsx | 17 +++++---- .../Comments/ThreadReplyArea.module.css | 4 ++ .../Comments/ThreadReplyArea.tsx | 37 +++++++++++-------- 15 files changed, 47 insertions(+), 23 deletions(-) diff --git a/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json b/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json index 289b1d10..d83a6d32 100644 --- a/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json +++ b/Parlance/ClientApp/public/resources/translations/cs-CZ/translation.json @@ -80,6 +80,7 @@ "CLOSE": "", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS_few": "", "COMMENT_OPEN_THREADS_one": "", "COMMENT_OPEN_THREADS_other": "", diff --git a/Parlance/ClientApp/public/resources/translations/da/translation.json b/Parlance/ClientApp/public/resources/translations/da/translation.json index ff46cee3..fdc779be 100644 --- a/Parlance/ClientApp/public/resources/translations/da/translation.json +++ b/Parlance/ClientApp/public/resources/translations/da/translation.json @@ -81,6 +81,7 @@ "CLOSE": "Luk", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS": "", "COMMENT_POST": "", "COMMENT_POSTING_AS_PROMPT": "", diff --git a/Parlance/ClientApp/public/resources/translations/de/translation.json b/Parlance/ClientApp/public/resources/translations/de/translation.json index 2823fe54..9568f8c1 100644 --- a/Parlance/ClientApp/public/resources/translations/de/translation.json +++ b/Parlance/ClientApp/public/resources/translations/de/translation.json @@ -81,6 +81,7 @@ "CLOSE": "Schließen", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS": "", "COMMENT_POST": "", "COMMENT_POSTING_AS_PROMPT": "", diff --git a/Parlance/ClientApp/public/resources/translations/en/translation.json b/Parlance/ClientApp/public/resources/translations/en/translation.json index 040937c8..632a2e87 100644 --- a/Parlance/ClientApp/public/resources/translations/en/translation.json +++ b/Parlance/ClientApp/public/resources/translations/en/translation.json @@ -83,6 +83,7 @@ "CLOSE": "Close", "COMMENTS": "Comments", "COMMENT_ADD": "Add Comment", + "COMMENT_NOT_LOGGED_IN_PROMPT": "Log in to write a comment", "COMMENT_OPEN_THREADS_one": "{{count}} open thread", "COMMENT_OPEN_THREADS_other": "{{count}} open threads", "COMMENT_POST": "Post Comment", diff --git a/Parlance/ClientApp/public/resources/translations/es/translation.json b/Parlance/ClientApp/public/resources/translations/es/translation.json index c835126d..23e57bfc 100644 --- a/Parlance/ClientApp/public/resources/translations/es/translation.json +++ b/Parlance/ClientApp/public/resources/translations/es/translation.json @@ -81,6 +81,7 @@ "CLOSE": "", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS": "", "COMMENT_POST": "", "COMMENT_POSTING_AS_PROMPT": "", diff --git a/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json b/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json index 467fea61..01ec6de4 100644 --- a/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json +++ b/Parlance/ClientApp/public/resources/translations/fr-CA/translation.json @@ -81,6 +81,7 @@ "CLOSE": "Fermer", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS_one": "", "COMMENT_OPEN_THREADS_other": "", "COMMENT_POST": "", diff --git a/Parlance/ClientApp/public/resources/translations/he-IL/translation.json b/Parlance/ClientApp/public/resources/translations/he-IL/translation.json index d14d62bd..c1fd7035 100644 --- a/Parlance/ClientApp/public/resources/translations/he-IL/translation.json +++ b/Parlance/ClientApp/public/resources/translations/he-IL/translation.json @@ -84,6 +84,7 @@ "CLOSE": "סגור", "COMMENTS": "תגובות", "COMMENT_ADD": "הוסף תגובה", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS_one": "פתוח שרשור תגובות {{count}}", "COMMENT_OPEN_THREADS_other": "פתוחים {{count}} שרשורי תגובות", "COMMENT_OPEN_THREADS_two": "פתוחים {{count}} שרשורי תגובות", diff --git a/Parlance/ClientApp/public/resources/translations/nl/translation.json b/Parlance/ClientApp/public/resources/translations/nl/translation.json index ad4432bf..ad626487 100644 --- a/Parlance/ClientApp/public/resources/translations/nl/translation.json +++ b/Parlance/ClientApp/public/resources/translations/nl/translation.json @@ -81,6 +81,7 @@ "CLOSE": "Sluiten", "COMMENTS": "Reacties", "COMMENT_ADD": "Reactie Toevoegen", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS_one": "{{count}} open thread", "COMMENT_OPEN_THREADS_other": "", "COMMENT_POST": "Reactie Plaatsen", diff --git a/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json b/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json index bbd145bc..4deb8b41 100644 --- a/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json +++ b/Parlance/ClientApp/public/resources/translations/pt-BR/translation.json @@ -81,6 +81,7 @@ "CLOSE": "Fechar", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS": "", "COMMENT_POST": "", "COMMENT_POSTING_AS_PROMPT": "", diff --git a/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json b/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json index 240584b4..22d2716b 100644 --- a/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json +++ b/Parlance/ClientApp/public/resources/translations/ro-RO/translation.json @@ -81,6 +81,7 @@ "CLOSE": "Închide", "COMMENTS": "Comentarii", "COMMENT_ADD": "Adaugă un comentariu", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS_few": "{{count}} conversații deschise", "COMMENT_OPEN_THREADS_one": "{{count}} conversație deschisă", "COMMENT_OPEN_THREADS_other": "{{count}} de conversații deschise", diff --git a/Parlance/ClientApp/public/resources/translations/uk/translation.json b/Parlance/ClientApp/public/resources/translations/uk/translation.json index 571cf104..f2644081 100644 --- a/Parlance/ClientApp/public/resources/translations/uk/translation.json +++ b/Parlance/ClientApp/public/resources/translations/uk/translation.json @@ -81,6 +81,7 @@ "CLOSE": "", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS": "", "COMMENT_POST": "", "COMMENT_POSTING_AS_PROMPT": "", diff --git a/Parlance/ClientApp/public/resources/translations/vi/translation.json b/Parlance/ClientApp/public/resources/translations/vi/translation.json index 8f7a2ab0..f59c3ba7 100644 --- a/Parlance/ClientApp/public/resources/translations/vi/translation.json +++ b/Parlance/ClientApp/public/resources/translations/vi/translation.json @@ -82,6 +82,7 @@ "CLOSE": "Đóng", "COMMENTS": "", "COMMENT_ADD": "", + "COMMENT_NOT_LOGGED_IN_PROMPT": "", "COMMENT_OPEN_THREADS_other": "", "COMMENT_POST": "", "COMMENT_POSTING_AS_PROMPT": "", diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx index 22eeed17..aeb5d4f8 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/CommentsModal.tsx @@ -10,6 +10,7 @@ import ThreadView from "./ThreadView"; import ThreadReplyArea from "./ThreadReplyArea"; import {Thread} from "../../../../../../../interfaces/comments"; import {ThreadItem} from "../../../../../../../components/comments/ThreadItem"; +import UserManager from "../../../../../../../helpers/UserManager"; export function CommentsModal({project, subproject, language, tkey, threads, onUpdateThreads}: { @@ -42,13 +43,15 @@ export function CommentsModal({project, subproject, language, tkey, threads, onU {threads.map((x, i) => ) || t("THREADS_NO_THREADS")} - -
- {t("THREADS_NEW_THREAD")} -
- -
+ {UserManager.currentUser && <> + +
+ {t("THREADS_NEW_THREAD")} +
+ +
+ } } } diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.module.css b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.module.css index 65b15e92..f9d1b8c0 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.module.css +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.module.css @@ -50,4 +50,8 @@ input.titleBox { align-items: center; padding: 9px; gap: 6px; +} + +.loggedOutMessage { + padding: 9px; } \ No newline at end of file diff --git a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx index e317a0e8..aa1b9efd 100644 --- a/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx +++ b/Parlance/ClientApp/src/pages/Projects/Subprojects/Languages/Translation/TranslationEditor/Comments/ThreadReplyArea.tsx @@ -93,23 +93,28 @@ export default function ThreadReplyArea({ } return
- {!threadId && setTitle(e.target.value)}/>} -