Add fix message replacement in translation form and lint page

This commit is contained in:
Simon Prévost 2024-03-28 21:04:26 -04:00
parent c0c8d83c54
commit 4079f5a01b
16 changed files with 192 additions and 16 deletions

View File

@ -4,7 +4,6 @@ defmodule AccentTest.ExportController do
alias Accent.Document
alias Accent.Language
alias Accent.Project
alias Accent.Repo
alias Accent.Revision
alias Accent.Translation
alias Accent.User
@ -308,6 +307,8 @@ defmodule AccentTest.ExportController do
end
if Langue.Formatter.Rails.enabled?() do
alias Accent.Repo
test "export with language overrides", %{conn: conn, project: project, revision: revision} do
revision = Repo.update!(Ecto.Changeset.change(revision, %{slug: "testtest"}))
document = Factory.insert(Document, project_id: project.id, path: "test2", format: "rails_yml")

View File

@ -4,7 +4,6 @@ defmodule AccentTest.ExportJIPTController do
alias Accent.Document
alias Accent.Language
alias Accent.Project
alias Accent.Repo
alias Accent.Revision
alias Accent.Translation
alias Accent.User
@ -125,6 +124,8 @@ defmodule AccentTest.ExportJIPTController do
end
if Langue.Formatter.Rails.enabled?() do
alias Accent.Repo
test "export with language overrides", %{conn: conn, project: project, revision: revision, language: language} do
revision = Repo.update!(Ecto.Changeset.change(revision, %{slug: "testtest"}))
document = Factory.insert(Document, project_id: project.id, path: "test2", format: "rails_yml")

View File

@ -1,4 +1,9 @@
import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking';
import Component from '@glimmer/component';
import {restartableTask} from 'ember-concurrency';
import translationUpdateQuery from 'accent-webapp/queries/update-translation';
import Apollo from 'accent-webapp/services/apollo';
interface Args {
project: any;
@ -12,6 +17,12 @@ interface Stat {
}
export default class LintTranslationsPage extends Component<Args> {
@service('apollo')
apollo: Apollo;
@tracked
fixLintMessageRunningTranslationId: string | null = null;
get lintTranslationsStatsCount() {
return this.lintTranslationsStats.reduce(
(total, stat) => stat.count + total,
@ -37,4 +48,21 @@ export default class LintTranslationsPage extends Component<Args> {
count
})) as Stat[];
}
fixLintMessageTask = restartableTask(
async (translation: {id: string}, message: any) => {
this.fixLintMessageRunningTranslationId = translation.id;
await this.apollo.client.mutate({
mutation: translationUpdateQuery,
refetchQueries: ['Lint'],
variables: {
text: message.replacement.value,
translationId: translation.id
}
});
this.fixLintMessageRunningTranslationId = null;
}
);
}

View File

@ -4,6 +4,7 @@ import parsedKeyProperty from 'accent-webapp/computed-macros/parsed-key';
interface Args {
lintTranslation: any;
project: any;
fix?: (lintTranslation: any, message: any) => void;
}
const escape = document.createElement('textarea');
@ -15,6 +16,14 @@ const escapeHTML = (html: string): string => {
export default class LintTranslationsPageItem extends Component<Args> {
translationKey = parsedKeyProperty(this.args.lintTranslation.translation.key);
get allReplacable() {
return this.args.lintTranslation.messages.every(
(message: {replacement: object | null}) => {
return Boolean(message.replacement);
}
);
}
get messages() {
const mapSet = new Set();
return this.args.lintTranslation.messages.flatMap((message: any) => {

View File

@ -26,6 +26,13 @@
}
}
&:global(.button--iconOnly) {
.label {
padding-left: 5px;
padding-right: 5px;
}
}
&:global(.button--small) {
&.button--loading {
.loading {

View File

@ -23,6 +23,12 @@
.item {
margin-bottom: 20px;
transition: 0.2s ease-in-out;
transition-property: opacity;
}
.item--fixing {
opacity: 0.5;
}
.icon-warning {
@ -46,10 +52,9 @@
.stats-item {
display: inline-flex;
gap: 4px;
padding: 2px 12px;
padding: 4px 12px;
border-radius: 30px;
border: 1px solid var(--background-light-highlight);
background: var(--background-light);
background: var(--background-light-highlight);
color: var(--text-color-normal);
font-size: 12px;
cursor: default;

View File

@ -13,11 +13,26 @@
flex-direction: column;
}
.messages-item {
display: flex;
gap: 4px;
align-items: center;
}
.description {
color: var(--color-error);
font-size: 12px;
}
.button-fix {
width: max-content;
&:focus,
&:hover {
--button-text-hover-color: var(--color-green);
}
}
.item-language {
font-size: 11px;
font-weight: bold;
@ -94,6 +109,15 @@
}
}
.item-diff-text {
font-size: 13px;
color: var(--text-color-normal);
> div {
display: inline;
}
}
.item-text {
strong {
color: var(--color-green);

View File

@ -187,3 +187,12 @@
margin-right: 6px;
stroke: var(--color-black);
}
.lint-messages {
transition: 0.2s ease-in-out;
transition-property: opacity;
}
.lint-messages--loading {
opacity: 0.5;
}

View File

@ -76,6 +76,18 @@
}
}
.button--blue {
--button-text-color: var(--color-blue);
}
.button--green {
--button-text-color: var(--color-green);
}
.button--grey {
--button-text-color: var(--color-grey);
}
.button--grey,
.button--success,
.button--black,

View File

@ -15,8 +15,8 @@
</div>
{{#each @lintTranslations key='id' as |lintTranslation|}}
<div local-class='item'>
<LintTranslationsPage::Item @project={{@project}} @lintTranslation={{lintTranslation}} />
<div local-class='item {{if (eq this.fixLintMessageRunningTranslationId lintTranslation.translation.id) "item--fixing"}}'>
<LintTranslationsPage::Item @project={{@project}} @lintTranslation={{lintTranslation}} @fixText={{perform this.fixLintMessageTask}} />
</div>
{{/each}}
</div>

View File

@ -2,13 +2,15 @@
<div local-class='wrapper' class='lint-translations-item'>
<ul local-class='messages'>
{{#each this.messages as |message|}}
<span local-class='description'>
{{#if message.message}}
{{message.message}}
{{else}}
{{t (concat 'components.translation_edit.lint_message.checks.' message.check)}}
{{/if}}
</span>
<li local-class='messages-item'>
<span local-class='description'>
{{#if message.message}}
{{message.message}}
{{else}}
{{t (concat 'components.translation_edit.lint_message.checks.' message.check)}}
{{/if}}
</span>
</li>
{{/each}}
</ul>
@ -29,6 +31,32 @@
</div>
{{/if}}
<div local-class='item-text'>{{{this.annotatedText}}}</div>
{{#if this.allReplacable}}
<ul>
{{#each this.messages as |message|}}
{{#if message.replacement}}
<li local-class='item-diff-text'>
<div>
{{string-diff message.replacement.value message.text}}
</div>
{{#if @changeText}}
<button {{on 'click' (fn @changeText message.replacement.value)}} class='button button--iconOnly button--borderless button--grey' local-class='button-fix'>
{{inline-svg '/assets/arrow-right.svg' class='button-icon'}}
</button>
{{/if}}
{{#if @fixText}}
<button {{on 'click' (fn @fixText @lintTranslation.translation message)}} class='button button--iconOnly button--borderless button--green' local-class='button-fix'>
{{inline-svg '/assets/check.svg' class='button-icon'}}
</button>
{{/if}}
</li>
{{/if}}
{{/each}}
</ul>
{{else}}
<div local-class='item-text'>{{{this.annotatedText}}}</div>
{{/if}}
</div>
{{/if}}

View File

@ -115,5 +115,7 @@
</div>
{{/if}}
<LintTranslationsPage::Item @lintTranslation={{this.lintTranslation}} />
<div local-class='lint-messages {{if this.fetchLintMessagesTask.isRunning "lint-messages--loading"}}'>
<LintTranslationsPage::Item @lintTranslation={{this.lintTranslation}} @changeText={{fn @onKeyUp}} />
</div>
</div>

View File

@ -0,0 +1,12 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
class="feather feather-arrow-right"
viewBox="0 0 24 24"
>
<path d="M5 12h14M12 5l7 7-7 7" />
</svg>

After

Width:  |  Height:  |  Size: 256 B

View File

@ -0,0 +1,12 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
class="feather feather-arrow-up"
viewBox="0 0 24 24"
>
<path d="M12 19V5M5 12l7-7 7 7" />
</svg>

After

Width:  |  Height:  |  Size: 253 B

View File

@ -0,0 +1,13 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
class="feather feather-check-circle"
viewBox="0 0 24 24"
>
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
<path d="M22 4 12 14.01l-3-3" />
</svg>

After

Width:  |  Height:  |  Size: 305 B

View File

@ -0,0 +1,13 @@
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
class="feather feather-check-square"
viewBox="0 0 24 24"
>
<path d="m9 11 3 3L22 4" />
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" />
</svg>

After

Width:  |  Height:  |  Size: 323 B