Assign and view translator

This commit is contained in:
kngako
2022-06-22 02:25:56 +02:00
parent dc37529d49
commit 180d7241ad
9 changed files with 337 additions and 20 deletions

16
package-lock.json generated
View File

@@ -1426,7 +1426,7 @@
},
"node_modules/mantra-db-models": {
"version": "0.0.10",
"resolved": "git+https://code.sigidli.com/mantra/mantra-db-models.git#40423458f5e549406ebf5433073d135497d7ec79",
"resolved": "git+https://code.sigidli.com/mantra/mantra-db-models.git#c26cf2b6a0d789b4441d4c76443ac419ae787b7c",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.0.1",
@@ -1518,9 +1518,9 @@
}
},
"node_modules/minipass": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.3.tgz",
"integrity": "sha512-N0BOsdFAlNRfmwMhjAsLVWOk7Ljmeb39iqFlsV1At+jqRhSUP9yeof8FyJu4imaJiSUp8vQebWD/guZwGQC8iA==",
"dependencies": {
"yallist": "^4.0.0"
},
@@ -4011,7 +4011,7 @@
}
},
"mantra-db-models": {
"version": "git+https://code.sigidli.com/mantra/mantra-db-models.git#40423458f5e549406ebf5433073d135497d7ec79",
"version": "git+https://code.sigidli.com/mantra/mantra-db-models.git#c26cf2b6a0d789b4441d4c76443ac419ae787b7c",
"from": "mantra-db-models@git+https://code.sigidli.com/mantra/mantra-db-models.git",
"requires": {
"bcrypt": "^5.0.1",
@@ -4079,9 +4079,9 @@
}
},
"minipass": {
"version": "3.1.6",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
"integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.3.tgz",
"integrity": "sha512-N0BOsdFAlNRfmwMhjAsLVWOk7Ljmeb39iqFlsV1At+jqRhSUP9yeof8FyJu4imaJiSUp8vQebWD/guZwGQC8iA==",
"requires": {
"yallist": "^4.0.0"
}

View File

@@ -1164,6 +1164,21 @@ module.exports = function (options) {
},
{
association: db.TranslationChapter.TranslationChapterTranslators,
include: [
{
association: db.TranslationChapterTranslator.Translator,
include: [
{
association: db.Entity.EntityEmail,
include: [
{
association: db.EntityEmail.Email
}
]
}
]
}
]
},
{
association: db.TranslationChapter.TranslationChapterProofReaders,

View File

@@ -1,5 +1,6 @@
const express = require('express')
const { Op } = require("sequelize")
const idGenerator = require('mantra-db-models/src/lib/id-generator')
module.exports = function (options) {
const db = options.db;
@@ -111,6 +112,21 @@ module.exports = function (options) {
},
{
association: db.TranslationChapter.TranslationChapterTranslators,
include: [
{
association: db.TranslationChapterTranslator.Translator,
include: [
{
association: db.Entity.EntityEmail,
include: [
{
association: db.EntityEmail.Email
}
]
}
]
}
]
},
{
association: db.TranslationChapter.TranslationChapterProofReaders,
@@ -849,5 +865,208 @@ module.exports = function (options) {
next(error)
})
})
router.route('/:id/chapter/:chapterId/translator')
.get(function(request, response, next) {
db.TranslationChapter.findByPk(request.params.chapterId, {
include: [
{
association: db.TranslationChapter.Chapter,
},
{
association: db.TranslationChapter.TranslationChapterTranslators,
},
{
association: db.TranslationChapter.TranslationChapterProofReaders,
},
{
association: db.TranslationChapter.TranslationChunks,
include: [
{
association: db.TranslationChunk.Translation
}
]
},
{
association: db.TranslationChapter.TranslationArtifactVersion,
include: [
{
association: db.TranslationArtifactVersion.ArtifactVersion,
include: [
{
association: db.ArtifactVersion.Artifact,
include: [
{
association: db.Artifact.Dialect
}
]
}
]
},
{
association: db.TranslationArtifactVersion.Dialect
},
{
association: db.TranslationArtifactVersion.BackTranslationFrom
},
{
association: db.TranslationArtifactVersion.TranslationArtifactVersionEditor,
}
]
}
]
}).then(translationChapter => {
if (translationChapter) {
response.display("translate-chapter-translator-form", {
user: request.user,
pageTitle: `Translate Chapter ${translationChapter.name}`,
translationChapter: translationChapter
})
} else {
next()
}
}).catch(error => {
next(error)
})
})
.post(function(request, response, next) {
db.TranslationChapter.findByPk(request.params.chapterId, {
include: [
{
association: db.TranslationChapter.Chapter,
},
{
association: db.TranslationChapter.TranslationChapterTranslators,
},
{
association: db.TranslationChapter.TranslationChapterProofReaders,
},
{
association: db.TranslationChapter.TranslationChunks,
include: [
{
association: db.TranslationChunk.Translation
}
]
},
{
association: db.TranslationChapter.TranslationArtifactVersion,
include: [
{
association: db.TranslationArtifactVersion.ArtifactVersion,
include: [
{
association: db.ArtifactVersion.Artifact,
include: [
{
association: db.Artifact.Dialect
}
]
}
]
},
{
association: db.TranslationArtifactVersion.Dialect
},
{
association: db.TranslationArtifactVersion.BackTranslationFrom
},
{
association: db.TranslationArtifactVersion.TranslationArtifactVersionEditor,
}
]
}
]
}).then(async (translationChapter) => {
if (translationChapter) {
// TODO: Check if translationChapter has a TranslationChapterTranslator with this email...
// TODO: FindOrCreate Email
const [email, created] = await db.Email.findOrCreate({
where: {
address: request.body.translator
},
include: [
{
association: db.Email.EntityEmails,
required: false,
where: {
creatorId: request.user.id
}
},
{
association: db.Email.UserEmail,
include: [
{
association: db.UserEmail.User,
include: [
{
association: db.User.IndividualEntityUser,
include: [
{
association: db.IndividualEntityUser.EntityUser
}
]
}
]
}
]
}
],
defaults: {
address: request.body.translator
}
})
console.log("Email: ", email.toJSON())
if (email.userEmail) {
// if email has user associated with it tie that users individual entity to a new TranslationChapterTranslator object
await db.TranslationChapterTranslator.create({
translationChapterId: translationChapter.id,
creatorId: request.user.id,
translatorId: email.userEmail.user.individualEntityUser.entityUser.entityId
})
} else if (email.entityEmails?.length > 0) {
// TODO: If email has an EntityEmail (which has this user as a creator) tie that entityEmail to a new TranslationChapterTranslator
await db.TranslationChapterTranslator.create({
translationChapterId: translationChapter.id,
creatorId: request.user.id,
translatorId: email.entityEmails[0].entityId
})
} else {
// if email doesn't have a user/entityEmail associated with it (newly created) create an EntityEmail and tie it to a new TranslationChapterTranslator object
await db.TranslationChapterTranslator.create({
translationChapterId: translationChapter.id,
creatorId: request.user.id,
translator: {
name: idGenerator.generateRandomAlphanumeric(),
type: "individual",
entityEmail: {
creatorId: request.user.id,
emailAddress: email.address,
type: 'translator'
}
}
}, {
include: [
{
association: db.TranslationChapterTranslator.Translator,
include: [
{
association: db.Entity.EntityEmail
}
]
}
]
})
}
response.redirect(`/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}`)
} else {
next()
}
}).catch(error => {
next(error)
})
})
return router;
};

View File

@@ -59,4 +59,18 @@ html {
.tracker-dropdown {
margin-left: 0;
margin-top: -2px;
}
.initial-icon {
display:inline-block;
font-size:1em;
width:2.5em;
height:2.5em;
line-height:2.5em;
text-align:center;
border-radius:50%;
background:plum;
vertical-align:middle;
margin-right:1em;
color:white;
}

View File

@@ -0,0 +1,4 @@
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('#translator-input');
var instances = M.Autocomplete.init(elems, {});
});

View File

@@ -0,0 +1,4 @@
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('#translator-dropdown');
var instances = M.Dropdown.init(elems, {});
});

View File

@@ -45,18 +45,43 @@ block content
a.dropdown-trigger editor ▼
tbody
each translationChapter in translationChapters.sort((a, b) => a.index - b.index)
tr(onclick=`window.location='/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}'`)
-
const onclickResponse = `window.location='/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}'`
tr
//- TODO: link to the translationChapter...
td
p
label
input(type="checkbox")
//- TODO: Make this a issueId...
input(name="selectedTranslationChapters", type="checkbox", value=translationChapter.id)
span
td.truncate(title=translationChapter.chapter.name)= translationChapter.chapter.name
td
td(onclick=onclickResponse)
span.truncate(title=translationChapter.chapter.name)= translationChapter.chapter.name
td(onclick=onclickResponse)
a(href=`/projects/${project.id}/tracker?dialectId=${translationChapter.translationArtifactVersion.dialect.id}`)= translationChapter.translationArtifactVersion.dialect.name
td #{translationChapter.translationArtifactVersion.artifactVersion.artifact.name} - #{translationChapter.translationArtifactVersion.artifactVersion.tag}
td= translationChapter.index
td
td
td
-
const artifactName = `${translationChapter.translationArtifactVersion.artifactVersion.artifact.name} - ${translationChapter.translationArtifactVersion.artifactVersion.tag}`
td(onclick=onclickResponse)
span.truncate(title=artifactName)= artifactName
td(onclick=onclickResponse)= translationChapter.index
td(onclick=onclickResponse)
each translationChapterTranslator in translationChapter.translationChapterTranslators
a(href=`/projects/${project.id}/tracker?translatorId=${translationChapterTranslator.translatorId}`)
-
const translatorDisplayName = translationChapterTranslator.translator.entityEmail == null ? translationChapterTranslator.translator.name : translationChapterTranslator.translator.entityEmail.email.address
const stringToColour = function(str) {
var hash = 0;
for (var i = 0; i < str.length; i++) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}
var colour = '#';
for (var i = 0; i < 3; i++) {
var value = (hash >> (i * 8)) & 0xFF;
colour += ('00' + value.toString(16)).substr(-2);
}
return colour;
}
span.initial-icon(style=`background: ${stringToColour(translationChapterTranslator.translatorId)};`, title=translatorDisplayName)= translatorDisplayName.split(" ").map(l => l.at(0)).join("")
td(onclick=onclickResponse)
td(onclick=onclickResponse)

View File

@@ -0,0 +1,28 @@
extend templates/layout.pug
block content
.container
.center
h1 #{translationChapter.translationArtifactVersion.artifactVersion.artifact.dialect.name} to #{translationChapter.translationArtifactVersion.name}
h2= translationChapter.translationArtifactVersion.artifactVersion.artifact.name
p.flow-text
span.chip #{translationChapter.chapter.wordCount.toLocaleString()} words
p.flow-text Add translator
form.row(action=`/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}/translator`, method="post")
.col.s12
.row
.input-field.col.s12
i.material-icons.prefix translate
input#translator-input.autocomplete(type="text", name="translator", required=true)
label(for="translator-input") Enter translators email
//- TODO add other functionality... phone number or username
block additionalScripts
script
include js/init-translator-autocomplete.js

View File

@@ -13,9 +13,13 @@ block content
.col.s12.m4
p.flow-text
a.btn-flat.waves-effect Translator &#x25BC;
a.btn-flat.waves-effect.dropdown-trigger(href=`/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}/translator`) Translator &#x25BC;
br
if translationChapter.translationChapterTranslators.length > 0
span With #{translationChapter.translationChapterTranslators.length} translator(s) assigned
each translationChapterTranslator in translationChapter.translationChapterTranslators
-
const translatorDisplayName = translationChapterTranslator.translator.entityEmail == null ? translationChapterTranslator.translator.name : translationChapterTranslator.translator.entityEmail.email.address
span.chip= translatorDisplayName
else
span No translators assigned yet
.col.s12.m4
@@ -64,4 +68,8 @@ block content
else if translationChunk.translation
a.btn.blue(href=`/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}/t/${translationChunk.index}`) edit
else
a.btn.black(href=`/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}/t/${translationChunk.index}`) translate
a.btn.black(href=`/translate/${translationChapter.translationArtifactVersion.id}/chapter/${translationChapter.id}/t/${translationChunk.index}`) translate
block additionalScripts
script
include js/init-translator-dropdown.js