From da9d91502cd366b60d35bff1fafa0be17f70248b Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Sat, 25 Dec 2021 01:35:32 +0200 Subject: [PATCH] Add versioning --- server/router/index.js | 3 +- server/router/library/index.js | 221 ++--------------- server/router/translate/index.js | 36 ++- server/router/versions/index.js | 268 +++++++++++++++++++++ server/views/chapter-form.pug | 8 +- server/views/chapter.pug | 2 +- server/views/entry-version.pug | 35 +++ server/views/entry.pug | 26 +- server/views/library-form.pug | 4 + server/views/translate-chapter.pug | 10 +- server/views/translate-chunk.pug | 12 +- server/views/translation-entry-version.pug | 9 + server/views/translation-entry.pug | 9 - server/views/translation-form.pug | 6 +- 14 files changed, 388 insertions(+), 261 deletions(-) create mode 100644 server/router/versions/index.js create mode 100644 server/views/entry-version.pug create mode 100644 server/views/translation-entry-version.pug delete mode 100644 server/views/translation-entry.pug diff --git a/server/router/index.js b/server/router/index.js index eec310a..6a29673 100644 --- a/server/router/index.js +++ b/server/router/index.js @@ -23,14 +23,15 @@ module.exports = function (options) { var campaignsRouter = require('./campaigns/')(options); var apiRouter = require('./api/')(options); var translateRouter = require('./translate/')(options); + var versionsRouter = require('./versions')(options); - router.use('/library', libraryRouter); router.use('/pledges', pledgesRouter); router.use('/campaigns', campaignsRouter); router.use('/account', accountRouter); router.use('/api', apiRouter); router.use('/translate', translateRouter); + router.use('/v', versionsRouter); return router; }; \ No newline at end of file diff --git a/server/router/library/index.js b/server/router/library/index.js index bb015e6..0692ca3 100644 --- a/server/router/library/index.js +++ b/server/router/library/index.js @@ -26,7 +26,9 @@ module.exports = function (options) { response.display("library-form", { user: request.user, pageTitle: "Add Library - Mantra", - entry: { } + entry: { + version: "1.0" + } }) } else { next() @@ -45,7 +47,19 @@ module.exports = function (options) { name: request.body.name, url: request.body.url, dialectId: dialect.id, - licenseId: "copyright" + licenseId: "copyright", + entryVersions: [ + { + tag: request.body.version + } + ] + }, { + include: [ + { + association: db.Entry.EntryVersions, + + } + ] }) } else { response.redirect("/library/add") // TODO: Show error message on missing dialect... @@ -74,85 +88,20 @@ module.exports = function (options) { association: db.Entry.EntryApproval }, { - association: db.Entry.Chapters - }, - { - association: db.Entry.TranslationEntries - } - ] - }).then(entry => { - response.display("entry", { - user: request.user, - pageTitle: "Library - Mantra", - entry: entry - }) - }).catch(error => { - next(error) - }) - }) - - router.route('/:id/chapters/add') - .get(function(request, response, next) { - db.Entry.findByPk(request.params.id, { - include: [ - { - association: db.Entry.EntryApproval - }, - { - association: db.Entry.Chapters + association: db.Entry.EntryVersions } ] }).then(entry => { if (entry) { - response.display("chapter-form", { - user: request.user, - pageTitle: "Library - Mantra", - entry: entry - }) - } else { - next() - } - - }).catch(error => { - next(error) - }) - }) - .post(function(request, response, next) { - db.Entry.findByPk(request.params.id, { - include: [ - { - association: db.Entry.EntryApproval - }, - { - association: db.Entry.Chapters - } - ] - }).then(entry => { - const isString = typeof request.body.text === "string" || request.body.text instanceof String - if (entry && isString) { - const chunks = request.body.text.trim().split(/\r?\n\r?\n/) - db.Chapter.create({ - name: chunks[0].trim(), - entryId: entry.id, - chunks: chunks.map((chunk,index) => { - return { - text: chunk, - index: index - } - }) - }, { - include: [ - { - association: db.Chapter.Chunks - } - ] - }).then(chapter => { - response.display("chapter-form", { + if (entry.entryVersions.length == 1) { + response.redirect(`/v/${entry.entryVersions[0].id}`) + } else { + response.display("entry", { user: request.user, pageTitle: "Library - Mantra", entry: entry }) - }) + } } else { next() @@ -162,131 +111,5 @@ module.exports = function (options) { }) }) - router.route('/:id/chapters/:chapterId') - .get(function(request, response, next) { - db.Chapter.findByPk(request.params.chapterId, { - include: [ - { - association: db.Chapter.Chunks - }, - { - association: db.Chapter.Entry - } - ] - }).then(chapter => { - if (chapter) { - response.display("chapter", { - user: request.user, - pageTitle: "Chapter - Mantra", - chapter: chapter - }) - } else { - next() - } - }).catch(error => { - next(error) - }) - }) - - router.route('/:id/translations/:translationEntryid') - .get(function(request, response, next) { - db.TranslationEntry.findByPk(request.params.translationEntryid, { - include: [ - { - association: db.TranslationEntry.Entry - } - ] - }).then(translationEntry => { - if (translationEntry) { - response.display("translation-entry", { - user: request.user, - pageTitle: "Translation Entry - Mantra", - translationEntry: translationEntry, - }) - } else { - next() - } - }).catch(error => { - next(error) - }) - }) - - router.route('/:id/translations/add') - .get(function(request, response, next) { - db.Entry.findByPk(request.params.id, { - include: [ - { - association: db.Entry.EntryApproval - }, - { - association: db.Entry.TranslationEntries - } - ] - }).then(entry => { - if (entry) { - response.display("translation-form", { - user: request.user, - pageTitle: "Library - Mantra", - entry: entry - }) - } else { - next() - } - - }).catch(error => { - next(error) - }) - }) - .post(function(request, response, next) { - db.Entry.findByPk(request.params.id, { - include: [ - { - association: db.Entry.EntryApproval - }, - { - association: db.Entry.TranslationEntries - }, - { - association: db.Entry.Chapters, - include: [ - { - association: db.Chapter.Chunks - } - ] - } - ] - }).then(async (entry) => { - if (entry) { - const dialectTokens = request.body.dialect?.split(":") - if (dialectTokens?.length == 2) { - const countryId = dialectTokens[0].split("-")[0] - const languageId = dialectTokens[0].split("-")[1] - - const dialect = await db.Dialect.findOne({ - where: { - countryId: countryId, - languageId: languageId - } - }) - - if (dialect) { - const translationEntry = await db.TranslationEntry.create({ - name: dialect.name, - entryId: entry.id, - dialectId: dialect.id - }) - - if (translationEntry) { - return response.redirect(`/library/${entry.id}/translations/${translationEntry.id}`) - } - } - } - } - next() - }).catch(error => { - next(error) - }) - }) - return router; }; \ No newline at end of file diff --git a/server/router/translate/index.js b/server/router/translate/index.js index d569b6b..98e42e1 100644 --- a/server/router/translate/index.js +++ b/server/router/translate/index.js @@ -7,14 +7,14 @@ module.exports = function (options) { router.route('/:id') .get(function(request, response, next) { - db.TranslationEntry.findByPk(request.params.id, { + db.TranslationEntryVersion.findByPk(request.params.id, { include: [ { - association: db.TranslationEntry.Entry, + association: db.TranslationEntryVersion.EntryVersion, required: true, include: [ { - association: db.Entry.Chapters, + association: db.EntryVersion.Chapters, required: true, limit: 1, // TODO: Order by chapter index @@ -22,9 +22,9 @@ module.exports = function (options) { ] } ] - }).then(translationEntry => { - if (translationEntry) { - response.redirect(`/translate/${translationEntry.id}/chapter/${translationEntry.entry.chapters[0].id}`) + }).then(translationEntryVersion => { + if (translationEntryVersion) { + response.redirect(`/translate/${translationEntryVersion.id}/chapter/${translationEntryVersion.entryVersion.chapters[0].id}`) } else { next() } @@ -44,18 +44,23 @@ module.exports = function (options) { ] }, { - association: db.Chapter.Entry, + association: db.Chapter.EntryVersion, required: true, include: [ { - association: db.Entry.TranslationEntries, + association: db.EntryVersion.TranslationEntryVersions, required: true, where: { id: request.params.id } }, { - association: db.Entry.Dialect + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.Dialect + } + ] } ] } @@ -99,18 +104,23 @@ module.exports = function (options) { required: true, include: [ { - association: db.Chapter.Entry, + association: db.Chapter.EntryVersion, required: true, include: [ { - association: db.Entry.TranslationEntries, + association: db.EntryVersion.TranslationEntryVersions, required: true, where: { id: request.params.id } }, { - association: db.Entry.Dialect + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.Dialect + } + ] } ] } @@ -122,7 +132,7 @@ module.exports = function (options) { const chunk = chunks.find(chunk => chunk.index == Number(request.params.chunkIndex)) response.display("translate-chunk", { user: request.user, - pageTitle: `Translate ${chunk.chapter.entry.name}`, + pageTitle: `Translate ${chunk.chapter.entryVersion.entry.name}`, chunk: chunk, previousChunk: chunks.find(chunk => chunk.index == previousIndex), nextChunk: chunks.find(chunk => chunk.index == nextIndex) diff --git a/server/router/versions/index.js b/server/router/versions/index.js new file mode 100644 index 0000000..cb2116c --- /dev/null +++ b/server/router/versions/index.js @@ -0,0 +1,268 @@ +const express = require('express'); +const req = require('express/lib/request'); + +module.exports = function (options) { + const db = options.db; + var router = express.Router(); + + router.route('/:id') + .get(function(request, response, next) { + db.EntryVersion.findByPk(request.params.id, { + include: [ + { + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.EntryApproval + } + ] + }, + { + association: db.EntryVersion.Chapters + }, + { + association: db.EntryVersion.TranslationEntryVersions + } + ] + }).then(entryVersion => { + if (entryVersion) { + response.display("entry-version", { + user: request.user, + pageTitle: "Entry - Mantra", + entryVersion: entryVersion + }) + } else { + next() + } + }).catch(error => { + next(error) + }) + }) + + router.route('/:id/chapters/add') + .get(function(request, response, next) { + db.EntryVersion.findByPk(request.params.id, { + include: [ + { + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.EntryApproval + } + ] + }, + { + association: db.EntryVersion.Chapters + } + ] + }).then(entryVersion => { + if (entryVersion) { + response.display("chapter-form", { + user: request.user, + pageTitle: "Library - Mantra", + entryVersion: entryVersion + }) + } else { + next() + } + + }).catch(error => { + next(error) + }) + }) + .post(function(request, response, next) { + db.EntryVersion.findByPk(request.params.id, { + include: [ + { + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.EntryApproval + } + ] + }, + { + association: db.EntryVersion.Chapters + } + ] + }).then(entryVersion => { + const isString = typeof request.body.text === "string" || request.body.text instanceof String + if (entryVersion && isString) { + const chunks = request.body.text.trim().split(/\r?\n\r?\n/) + db.Chapter.create({ + name: chunks[0].trim(), + entryVersionId: entryVersion.id, + chunks: chunks.map((chunk,index) => { + return { + text: chunk, + index: index + } + }) + }, { + include: [ + { + association: db.Chapter.Chunks + } + ] + }).then(chapter => { + if (chapter) { + response.redirect(`/v/${chapter.entryVersionId}/chapters/${chapter.id}`) + } else { + response.display("chapter-form", { + user: request.user, + pageTitle: "Library - Mantra", + entryVersion: entryVersion + }) + } + }).catch(error => { + next(error) + }) + + } else { + next() + } + }).catch(error => { + next(error) + }) + }) + + router.route('/:id/chapters/:chapterId') + .get(function(request, response, next) { + db.Chapter.findByPk(request.params.chapterId, { + include: [ + { + association: db.Chapter.Chunks + }, + { + association: db.Chapter.EntryVersion, + include: [ + { + association: db.EntryVersion.Entry + } + ] + } + ] + }).then(chapter => { + if (chapter) { + response.display("chapter", { + user: request.user, + pageTitle: "Chapter - Mantra", + chapter: chapter + }) + } else { + next() + } + }).catch(error => { + next(error) + }) + }) + + router.route('/:id/translations/:translationEntryVersionId') + .get(function(request, response, next) { + db.TranslationEntryVersion.findByPk(request.params.translationEntryVersionId, { + include: [ + { + association: db.TranslationEntryVersion.EntryVersion, + include: [ + { + association: db.EntryVersion.Entry + } + ] + } + ] + }).then(translationEntryVersion => { + if (translationEntryVersion) { + response.display("translation-entry-version", { + user: request.user, + pageTitle: "Translation Entry - Mantra", + translationEntryVersion: translationEntryVersion, + }) + } else { + next() + } + }).catch(error => { + next(error) + }) + }) + + router.route('/:id/translations/add') + .get(function(request, response, next) { + db.EntryVersion.findByPk(request.params.id, { + include: [ + { + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.EntryApproval + } + ] + }, + { + association: db.EntryVersion.TranslationEntryVersions + } + ] + }).then(entryVersion => { + if (entryVersion) { + response.display("translation-form", { + user: request.user, + pageTitle: "Library - Mantra", + entryVersion: entryVersion + }) + } else { + next() + } + + }).catch(error => { + next(error) + }) + }) + .post(function(request, response, next) { + db.EntryVersion.findByPk(request.params.id, { + include: [ + { + association: db.EntryVersion.Entry, + include: [ + { + association: db.Entry.EntryApproval + } + ] + }, + { + association: db.EntryVersion.TranslationEntryVersions + } + ] + }).then(async (entryVersion) => { + if (entryVersion) { + const dialectTokens = request.body.dialect?.split(":") + if (dialectTokens?.length == 2) { + const countryId = dialectTokens[0].split("-")[0] + const languageId = dialectTokens[0].split("-")[1] + + const dialect = await db.Dialect.findOne({ + where: { + countryId: countryId, + languageId: languageId + } + }) + + if (dialect) { + const translationEntryVersion = await db.TranslationEntryVersion.create({ + name: dialect.name, + entryVersionId: entryVersion.id, + dialectId: dialect.id + }) + + if (translationEntryVersion) { + return response.redirect(`/v/${entryVersion.id}/translations/${translationEntryVersion.id}`) + } + } + } + } + next() + }).catch(error => { + next(error) + }) + }) + + return router; +}; \ No newline at end of file diff --git a/server/views/chapter-form.pug b/server/views/chapter-form.pug index e3aa2e3..bc1c461 100644 --- a/server/views/chapter-form.pug +++ b/server/views/chapter-form.pug @@ -3,16 +3,16 @@ extend templates/layout.pug block content .container .center - h1 Chapter in #{entry.name} + h1 Chapter in #{entryVersion.name} .row .col.s12 - form.row(action=`/library/${entry.id}/chapters/add`, method="post") + form.row(action=`/v/${entryVersion.id}/chapters/add`, method="post") .col.s12.input-field textarea#textarea.materialize-textarea(name="text") - label(for="textarea") Chapter Text + label(for="textarea") Entire chapter text (markdown) .col.s12.input-field - input#index(type="number", name="index", value=entry.chapters.length+1) + input#index(type="number", name="index", value=entryVersion.chapters.length+1) label(for="index") Chapter Number .col.s12 button.btn.black(type="submit") add chapter \ No newline at end of file diff --git a/server/views/chapter.pug b/server/views/chapter.pug index 4eb5fe4..8b076aa 100644 --- a/server/views/chapter.pug +++ b/server/views/chapter.pug @@ -6,7 +6,7 @@ block content //- h1= chapter.name - a.btn.black(href=`/library/${chapter.entryId}`) go to entry + a.btn.black(href=`/v/${chapter.entryVersionId}`) go to entry .row each chunk in chapter.chunks diff --git a/server/views/entry-version.pug b/server/views/entry-version.pug new file mode 100644 index 0000000..aba9841 --- /dev/null +++ b/server/views/entry-version.pug @@ -0,0 +1,35 @@ +extend templates/layout.pug + +block content + .container + .center + h1 #{entryVersion.entry.name} + h2 #{entryVersion.tag} + + .divider + .row + a.btn.black(href=`/v/${entryVersion.id}/chapters/add`) add chapter + + if entryVersion.chapters.length == 0 + p.flow-text No chapters added + else + .row + each chapter in entryVersion.chapters + .col.s12 + a(href=`/v/${entryVersion.id}/chapters/${chapter.id}`) + .card-panel + p.flow-text= chapter.name + + .divider + .row + a.btn.black(href=`/v/${entryVersion.id}/translations/add`) add translation + + if entryVersion.translationEntryVersions.length == 0 + p.flow-text No chapters added + else + .row + each translationEntry in entryVersion.translationEntryVersions + .col.s12 + a(href=`/v/${entryVersion.id}/translations/${translationEntry.id}`) + .card-panel + p.flow-text= translationEntry.name \ No newline at end of file diff --git a/server/views/entry.pug b/server/views/entry.pug index 2eb502b..1dc23b9 100644 --- a/server/views/entry.pug +++ b/server/views/entry.pug @@ -7,28 +7,14 @@ block content .divider .row - a.btn.black(href=`/library/${entry.id}/chapters/add`) add chapter + a.btn.black(href=`/library/${entry.id}/version/add`) add version - if entry.chapters.length == 0 - p.flow-text No chapters added + if entry.entryVersions.length == 0 + p.flow-text No available versions else .row - each chapter in entry.chapters + each entryVersion in entry.entryVersions .col.s12 - a(href=`/library/${entry.id}/chapters/${chapter.id}`) + a(href=`/library/${entryVersion.entryId}/v/${entryVersion.id}`) .card-panel - p.flow-text= chapter.name - - .divider - .row - a.btn.black(href=`/library/${entry.id}/translations/add`) add translation - - if entry.translationEntries.length == 0 - p.flow-text No chapters added - else - .row - each translationEntry in entry.translationEntries - .col.s12 - a(href=`/library/${entry.id}/translations/${translationEntry.id}`) - .card-panel - p.flow-text= translationEntry.name \ No newline at end of file + p.flow-text= entryVersion.tag \ No newline at end of file diff --git a/server/views/library-form.pug b/server/views/library-form.pug index 1eab824..b77fc14 100644 --- a/server/views/library-form.pug +++ b/server/views/library-form.pug @@ -14,5 +14,9 @@ block content .col.s12.input-field input#url(type="text", name="url", value=entry.url) label(for="url") Entry Url + if entry.id == null + .col.s12.input-field + input#version(type="text", name="version", value=entry.version) + label(for="version") First Version Number .col.s12 button.btn.black(type="submit") add entry \ No newline at end of file diff --git a/server/views/translate-chapter.pug b/server/views/translate-chapter.pug index b4fb213..51d0d08 100644 --- a/server/views/translate-chapter.pug +++ b/server/views/translate-chapter.pug @@ -3,8 +3,8 @@ extend templates/layout.pug block content .container .center - h1= chapter.entry.translationEntries[0].name - h2= chapter.entry.name + h1= chapter.entryVersion.translationEntryVersions[0].name + h2= chapter.entryVersion.entry.name //- TODO: List chunks in the chapter .row @@ -12,8 +12,8 @@ block content table thead tr - th #{chapter.entry.dialect.name} - th #{chapter.entry.translationEntries[0].name} + th #{chapter.entryVersion.entry.dialect.name} + th #{chapter.entryVersion.translationEntryVersions[0].name} th tbody @@ -33,4 +33,4 @@ block content else if chunk.translation a.btn.blue review else - a.btn.black(href=`/translate/${chapter.entry.translationEntries[0].id}/chapter/${chapter.id}/t/${chunk.index}`) translate \ No newline at end of file + a.btn.black(href=`/translate/${chapter.entryVersion.translationEntryVersions[0].id}/chapter/${chapter.id}/t/${chunk.index}`) translate \ No newline at end of file diff --git a/server/views/translate-chunk.pug b/server/views/translate-chunk.pug index e2c12ee..9f02c19 100644 --- a/server/views/translate-chunk.pug +++ b/server/views/translate-chunk.pug @@ -3,10 +3,10 @@ extend templates/layout.pug block content .container .center - h1 Translate into #{chunk.chapter.entry.translationEntries[0].name} + h1 Translate into #{chunk.chapter.entryVersion.translationEntryVersions[0].name} //- TODO: Show previous... - form.row(action=`/translate/${chunk.chapter.entry.translationEntries[0].id}/chapter/${chunk.chapter.id}/t/${chunk.id}`) + form.row(action=`/translate/${chunk.chapter.entryVersion.translationEntryVersions[0].id}/chapter/${chunk.chapter.id}/t/${chunk.id}`) .col.s12.m6.input-field textarea#original-text.materialize-textarea(name="originalText")= chunk.text label(for="original-text") Original Text @@ -30,7 +30,7 @@ block content //- thead tr th #{chunk.chapter.entry.dialect.name} - th #{chunk.chapter.entry.translationEntries[0].name} + th #{chunk.chapter.entry.translationEntryVersions[0].name} th tbody tr @@ -48,7 +48,7 @@ block content else if previousChunk.translation a.btn.blue review else - a.btn.black(href=`/translate/${previousChunk.chapter.entry.translationEntries[0].id}/chapter/${previousChunk.chapter.id}/t/${previousChunk.index}`) previous translation + a.btn.black(href=`/translate/${previousChunk.chapter.entryVersion.translationEntryVersions[0].id}/chapter/${previousChunk.chapter.id}/t/${previousChunk.index}`) previous translation if nextChunk .col.s12#next-translation @@ -56,7 +56,7 @@ block content //- thead tr th #{chunk.chapter.entry.dialect.name} - th #{chunk.chapter.entry.translationEntries[0].name} + th #{chunk.chapter.entry.translationEntryVersions[0].name} th tbody tr @@ -74,7 +74,7 @@ block content else if nextChunk.translation a.btn.blue review else - a.btn.black(href=`/translate/${nextChunk.chapter.entry.translationEntries[0].id}/chapter/${nextChunk.chapter.id}/t/${nextChunk.index}`) next translation + a.btn.black(href=`/translate/${nextChunk.chapter.entryVersion.translationEntryVersions[0].id}/chapter/${nextChunk.chapter.id}/t/${nextChunk.index}`) next translation block additionalScripts diff --git a/server/views/translation-entry-version.pug b/server/views/translation-entry-version.pug new file mode 100644 index 0000000..f38be3b --- /dev/null +++ b/server/views/translation-entry-version.pug @@ -0,0 +1,9 @@ +extend templates/layout.pug + +block content + .container + .center + h1= translationEntryVersion.name + h2= translationEntryVersion.entryVersion.entry.name + + a.btn.black(href=`/translate/${translationEntryVersion.id}`) Translate \ No newline at end of file diff --git a/server/views/translation-entry.pug b/server/views/translation-entry.pug deleted file mode 100644 index 233e53b..0000000 --- a/server/views/translation-entry.pug +++ /dev/null @@ -1,9 +0,0 @@ -extend templates/layout.pug - -block content - .container - .center - h1= translationEntry.name - h2= translationEntry.entry.name - - a.btn.black(href=`/translate/${translationEntry.id}`) Translate \ No newline at end of file diff --git a/server/views/translation-form.pug b/server/views/translation-form.pug index da2d331..76c389e 100644 --- a/server/views/translation-form.pug +++ b/server/views/translation-form.pug @@ -3,15 +3,15 @@ extend templates/layout.pug block content .container .center - h1 Translation of #{entry.name} + h1 Translation of #{entryVersion.name} .row .col.s12 - form.row(action=`/library/${entry.id}/translations/add`, method="post") + form.row(action=`/v/${entryVersion.id}/translations/add`, method="post") .col.s12.input-field i.material-icons.prefix record_voice_over - input#dialect-autocomplete.autocomplete(type="text", name="dialect", required) + input#dialect-autocomplete.autocomplete(type="text", name="dialect", required, autocomplete="off") label(for="dialect-autocomplete") Dialect which this translation will be made in. .col.s12 button.btn.black(type="submit") add translation