Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

UI for form languages and translations #1913

Merged
merged 106 commits into from
Sep 24, 2018
Merged

Conversation

pmusaraj
Copy link
Contributor

@pmusaraj pmusaraj commented Aug 2, 2018

Description

This PR adds UI that lets users add and update translations on a form. See screenshots below for some details. When testing, please carefully review the changes in the form builder, the PR strips out a good amount of translation-related UI there.

Screenshots

screen shot 2018-08-02 at 11 49 07 am

screen shot 2018-08-02 at 11 52 25 am

screen shot 2018-08-02 at 11 52 36 am

screen shot 2018-08-02 at 11 53 07 am

Issues

I didn't have time to do one last feature here: allow users to either:

  • reorder languages or
  • set the default language (the one that's loaded in the form builder)

@magicznyleszek please look into the possibility of adding this feature (might require some backend work too)

Note: the PR also reorganizes the modal forms, by putting them all in a subfolder.

Related issues

Closes #1948
Closes #1273
Closes #1175
Closes #949
Closes #1166
Closes #1144
Closes #1381
Closes #327

Copy link
Member

@magicznyleszek magicznyleszek left a comment

Choose a reason for hiding this comment

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

Some thoughts:

  • it would be nice when adding a language to have ENTER key work
  • don't we want to suggest users some real world language-code pairs? No
  • when opening "Translations table" in modal, it would be nice to have "BACK" button
  • page input in "Translations table" changes height when empty
  • error when trying to delete language: translationSettings.es6:343 Uncaught TypeError: Cannot read property 'length' of undefined at TranslationSettings.deleteTranslations (translationSettings.es6:343) at TranslationSettings.deleteTranslations (createPrototypeProxy.js:44) at TranslationSettings.deleteLanguage (translationSettings.es6:270) at TranslationSettings.deleteLanguage (createPrototypeProxy.js:44) - language is still there, but translations table is empty
  • I had form with 1 question, I set default language to "English (en)" and added "Polski (pl)", then translated one string from the "Translations table". Then in form editor I added second question and saved. Now default language is "Unnamed language"
  • When I delete the only question language disappears
  • "SAVE CHANGES" button from "Translations table" could have pending state and be disabled for a while after clicking
  • there is no message in "Manage languages" if form has 0 questions
  • I have one non-default language and one translated question. I go to form editor and change the name of the question. Now the non-default language is completely removed.
  • Is it ok to allow adding multiple languages with the same code? You can even define same language multiple times. I believe it breaks form in Enketo
  • Templates should have translations!
  • I don't see language selector in Enketo for "Online-Offline (multiple submission)"
  • Should we have ability to edit translations from Form Editor? Better not yet turns out you can't manage languages, but you can manage translated labels already

screen shot 2018-08-03 at 17 18 36

screen shot 2018-08-03 at 17 18 58

screen shot 2018-08-03 at 18 40 22

screen shot 2018-08-03 at 18 50 15

return false;

return (
<bem.FormView__cell m={['columns', 'padding', 'bordertop', 'languages']}>
Copy link
Member

Choose a reason for hiding this comment

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

I know this was already there, but modifier named padding or bordertop seems like a Bad Code™

})}
</bem.FormView__cell>
{canEdit &&
<bem.FormView__cell m='languages-col2'>
Copy link
Member

Choose a reason for hiding this comment

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

maybe just languages-col and :nth-of-type() in css would be more maintainable?

languagesModal (evt) {
evt.preventDefault();
stores.pageState.showModal({
type: 'form-languages',
Copy link
Member

Choose a reason for hiding this comment

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

This should be from MODAL_TYPES from constants.es6

@@ -143,6 +109,13 @@ export class FormLanding extends React.Component {
asset: this.state
});
}
languagesModal (evt) {
Copy link
Member

Choose a reason for hiding this comment

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

showLanguagesModal sounds more like action

}
}
launchTranslationTableModal(e) {
let index = parseInt($(e.target).closest('[data-index]').get(0).getAttribute('data-index')),
Copy link
Member

Choose a reason for hiding this comment

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

wouldn't it be shorter and simpler if you would use evt.currentTarget?

asset: asset,
langIndex: index
});
}, 300);
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to wait for some event/action rather than random ms value? I'm ok with that if too hard to implement

Copy link
Member

Choose a reason for hiding this comment

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

I made this into stores.pageState.switchModal method with timeout 0 - hacky but couldn't find any better and quick solution

this.updateAsset(content);
}
deleteLanguage(e) {
let index = parseInt($(e.target).closest('[data-index]').get(0).getAttribute('data-index'));
Copy link
Member

Choose a reason for hiding this comment

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

same as above: currentTarget could be better here

deleteLanguage(e) {
let index = parseInt($(e.target).closest('[data-index]').get(0).getAttribute('data-index'));
let content = this.props.asset.content;
content = this.deleteTranslations(content, index);
Copy link
Member

Choose a reason for hiding this comment

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

const content = this.deleteTranslations(this.props.asset.content, index);

nitpicking

} else {
notify('Error: translation index mismatch. Cannot delete language.');
}

Copy link
Member

Choose a reason for hiding this comment

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

empty line

{t('Here you can add one more more languages to your project, and translate the strings in each language.')}
&nbsp;
<em>
{t('Note: make sure your default language has a name. If it doesn\'t, you will not be able to edit your form in the form builder.')}
Copy link
Member

@magicznyleszek magicznyleszek Aug 3, 2018

Choose a reason for hiding this comment

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

Maybe we should validate this form to not allow unnamed default language? We could use TextBox which handles errors

Copy link
Member

Choose a reason for hiding this comment

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

"Add language" button is disabled until default language is configured :)

Copy link
Member

@magicznyleszek magicznyleszek left a comment

Choose a reason for hiding this comment

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

Sorry for double review btw 😘 I finished reviewing and had this one thing plus some comments in the code:

  • in Translation table, the textarea element doesn't take whole vertical row space - looks weird when focused

screen shot 2018-08-04 at 09 25 57

jsapp/js/utils.es6 Outdated Show resolved Hide resolved
.form-view__cell {
min-width: 100px;

&--lang-code {
Copy link
Member

Choose a reason for hiding this comment

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

It's just my preference, but when I try to find form-view__cell--lang-code when debugging in Dev Tools, this notation makes it so much harder

width: 100%;
margin: 0;

.form-modal__item--translation-table--container {
Copy link
Member

Choose a reason for hiding this comment

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

Nitpicking: isn't this invalid BEM selector? I would go with .form-modal__item--translation-table-container

}
}

// alertify overrides
Copy link
Member

Choose a reason for hiding this comment

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

all those styles below should be in jsapp/scss/components/_kobo.alertify-overrides.scss (from quick look they seem to be 100% duplicated there, but better diffcheck it)

Copy link
Member

Choose a reason for hiding this comment

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

these were in fact duplicates plus an older version

# run()
expect(run).toThrow('There is an unnamed translation in your form definition')
# DISABLED
# CONSIDER DELETING BEFORE MERGING
Copy link
Member

Choose a reason for hiding this comment

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

I would definitely be for deleting all this commented out code, but writing at least some unit tests for translations - as mentioned in one of comments above :)

Copy link
Member

Choose a reason for hiding this comment

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

I added a pair of tests (could be more) and kept one of these here

@magicznyleszek
Copy link
Member

I merged recent master here and added one more change in line with:

Note: the PR also reorganizes the modal forms, by putting them all in a subfolder.

@pmusaraj
Copy link
Contributor Author

pmusaraj commented Aug 4, 2018

Leszek, thanks for the detailed review. If you have time to fix the many issues you’ve noticed and reorganize things (like use constants for the modal), please do. There probably should be a button in the form builder that triggers the languages.

@magicznyleszek
Copy link
Member

@pmusaraj I will start working on fixing what I've found :-)

@magicznyleszek magicznyleszek self-assigned this Aug 4, 2018
@jnm
Copy link
Member

jnm commented Sep 10, 2018

@magicznyleszek, re: "What is the real problem," did you see my comment above? When renaming the default language, you need to update default_language on the frontend before sending the asset content to the BE. Right now, you are asking the backend to set the default language to a translation that doesn't exist.

Regarding error messages:

  • Let's not end all errors with exclamation points;
  • The old convention was to use lowercase notifications, e.g. when updating translations succeeds, the message is successfully updated;
  • "failed to update translations" is more concise than "Failed language update attempt" (failing implies an attempt was made).

@pmusaraj
Copy link
Contributor Author

@jnm regarding the "Right now, I can't update b if it's set to the default, but I can update the unnamed translation" comment: the default language can currently only be edited in the form builder. we don't have an interface for updating it in the translations screens, since those strings are the base language.

I do see this can be confusing for a user, especially when changing the default language. I had earlier proposed (in Flowdock) we add a confirmation modal when setting a default language, we could let the user know in that screen that strings in the default language can only be edited in the FB.

@magicznyleszek
Copy link
Member

@jnm I fixed updating default_language :)

@magicznyleszek
Copy link
Member

magicznyleszek commented Sep 16, 2018

@jnm I moved nullifying hack code to a utils function. I tested both functions with few tests (+ fixed few things thanks to those test). The problem is that both of them work on different type of data, and to get from one to other it takes some form builder code. I don't know if this is testable as a full flow. It would be easier with Cypress probably

# Conflicts:
#	jsapp/js/components/formEditors.es6
@jnm jnm merged commit 8d0e95f into master Sep 24, 2018
@jnm jnm deleted the translations-formtemplates-merge branch September 24, 2018 15:41
@jnm jnm restored the translations-formtemplates-merge branch September 24, 2018 15:59
@jnm jnm deleted the translations-formtemplates-merge branch September 24, 2018 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
high priority To be done soon
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants