First full release

This commit is contained in:
Luka Romih
2023-03-10 12:50:23 +01:00
parent 257f3c354f
commit 9867875ef2
285 changed files with 10980 additions and 4692 deletions
+87 -161
View File
@@ -1,7 +1,9 @@
/* global $, axios, bootstrap, currentPagePath, initPagination, removeAllChildNodes, unsavedData */
/* global $, axios, bootstrap, currentPagePath, initPagination, removeAllChildNodes, unsavedData, replaceContainer, i18next */
// const currentPagePath = location.pathname
let queryBattery = ''
window.addEventListener('load', () => {
initAdmin()
})
@@ -62,11 +64,11 @@ function initAdmin() {
renderResults(results)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
@@ -130,11 +132,11 @@ function initAdmin() {
ifUserExists(data, type)
event.target.reset()
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
console.log(message)
}
@@ -155,11 +157,11 @@ function initAdmin() {
renderResults(results)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
@@ -189,9 +191,9 @@ function initAdmin() {
aEl.type = 'link'
aEl.href = `/admin/uporabniki/${result.id}/urejanje`
imgEl.src = '/images/u_edit-alt.svg'
imgEl.alt = 'Uredi'
imgEl.alt = i18next.t('Uredi')
spanEl.className = 'normal-gray ms-1'
spanEl.textContent = 'Uredi'
spanEl.textContent = i18next.t('Uredi')
td4.append(aEl)
aEl.append(imgEl, spanEl)
rowEl.append(td1, td2, td3, td4)
@@ -214,11 +216,11 @@ function initAdmin() {
renderResults(results)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
@@ -267,9 +269,9 @@ function initAdmin() {
aEl.type = 'link'
aEl.href = `/admin/slovarji/${result.id}/podatki`
imgEl.src = '/images/u_edit-alt.svg'
imgEl.alt = 'Uredi'
imgEl.alt = i18next.t('Uredi')
spanEl.className = 'normal-gray ms-1'
spanEl.textContent = 'Uredi'
spanEl.textContent = i18next.t('Uredi')
td6.append(aEl)
aEl.append(imgEl, spanEl)
rowEl.append(td1, td2, td3, td4, td5, td6)
@@ -343,18 +345,20 @@ function initAdmin() {
async function onPageChange(newPage) {
try {
const { page, numberOfAllPages, results } = await getDataForPage(
newPage
)
const results = await getDataForPage(newPage)
const numberOfAllPages = +results.headers['number-of-all-pages']
const page = +results.headers.page
removeAllChildNodes(resultsListEl)
renderResults(results)
renderResults(results.data)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
@@ -362,56 +366,46 @@ function initAdmin() {
}
async function getDataForPage(page) {
const url = `/api/v1/dictionaries/listSecondaryDomains?p=${page}`
const { data } = await axios.get(url)
return data
const url = `/api/v1/dictionaries/secondaryDomains?q=${queryBattery}&p=${page}`
return await axios.get(url)
}
function renderResults(results) {
results.forEach(result => {
const rowEl = document.createElement('tr')
const input = document.createElement('input')
const th = document.createElement('th')
const input2 = document.createElement('input')
const td1 = document.createElement('td')
const tdTrans = document.createElement('td')
const td2 = document.createElement('td')
const div = document.createElement('div')
const editBtn = document.createElement('button')
const deleteBtn = document.createElement('button')
const imgEditEl = document.createElement('img')
const imgDelEl = document.createElement('img')
input.value = result.id
input.type = 'hidden'
input.name = 'domainLabelId'
th.scope = 'row'
input2.className = 'form-check checkbox-table'
input2.type = 'checkbox'
input2.name = 'isVisible'
input2.disabled = true
input2.checked = !!result.isApproved
th.append(input2)
td1.className = 'tdata-area'
td1.textContent = result.nameSl
tdTrans.className = 'tdata-translation'
tdTrans.textContent = result.nameEn
td2.classList.add('buttons-group')
div.classList.add('table-buttons')
editBtn.className = 'p-0 table-button-grp me-3 edit-row-btn'
editBtn.type = 'button'
imgEditEl.src = '/images/u_edit-alt.svg'
deleteBtn.className = 'p-0 table-button-grp delete-row-btn'
deleteBtn.dataset.bsTarget = '#alert-modal'
deleteBtn.dataset.bsToggle = 'modal'
deleteBtn.type = 'button'
imgDelEl.src = '/images/red-trash-icon.svg'
td2.append(div)
div.append(editBtn, deleteBtn)
editBtn.append(imgEditEl)
deleteBtn.append(imgDelEl)
replaceContainer('page-results', results)
}
rowEl.append(input, th, td1, tdTrans, td2)
resultsListEl.appendChild(rowEl)
const updatePaginationOnFilter = axiosResult => {
const numberOfAllPages = +axiosResult.headers['number-of-all-pages']
const page = +axiosResult.headers.page
// removeAllChildNodes(resultsListEl)
// renderResults(results.data)
// console.log(numberOfAllPages)
// console.log(page)
// console.log(updatePager)
updatePager(page, numberOfAllPages)
}
/// / Due to unsual design, the function was moved inside
function searchController() {
// if (window.location.pathname.includes('podrocne-oznake')) { // No if required since already checkek above
queryBattery = document.getElementById('input-search').value
// console.log(queryBattery)
axios
.get(`/api/v1/dictionaries/secondaryDomains?q=${queryBattery}`)
.then(result => {
updatePaginationOnFilter(result)
replaceContainer('page-results', result.data)
})
// }
}
const inlineSearchButton = document.getElementById('inline-search-btn')
if (inlineSearchButton) {
inlineSearchButton.addEventListener('click', searchController)
$('#input-search').on('keyup', function (e) {
if (e.code === 'Enter' || e.code === 'NumpadEnter') {
searchController()
}
})
}
}
@@ -450,7 +444,7 @@ function initAdmin() {
ifUserExists(data, type)
event.target.reset()
} catch (error) {
const message = 'Prišlo je do napake.'
const message = i18next.t('Prišlo je do napake.')
}
}
}
@@ -460,17 +454,6 @@ function initAdmin() {
formEditUser.addEventListener('input', enableButton)
}
if (/\/slovarji\/\d+\/struktura/.test(currentPagePath)) {
changePreview()
const switchForm = document.querySelector('.switch-forms')
switchForm.addEventListener('click', () => changePreview())
const wholeForm = document.getElementById('form-dictionary-structure')
wholeForm.addEventListener('input', enableButton)
const dictSideMenu = document.querySelector('.admin-nav-content')
unsavedData(wholeForm, dictSideMenu)
$('#languages-input').on('change', enableButton)
}
if (currentPagePath === '/admin/nastavitve/portal') {
const formAdminPortal = document.getElementById('admin-portal-settings')
formAdminPortal.addEventListener('input', enableButton)
@@ -537,7 +520,7 @@ function createNewAuthorInput(pageForm) {
divAuthor.className = 'author mt-sm-4 added-field'
divSubjectName.className = 'subject-name'
spanName.className = 'smaller-gray-uppercase'
spanName.textContent = 'AVTOR'
spanName.textContent = i18next.t('AVTOR')
divRow.className = 'row align-items-center'
divColSm5.className = 'col-sm-6'
inputGroup.className = 'input-group'
@@ -553,7 +536,7 @@ function createNewAuthorInput(pageForm) {
divColSm.className = 'col-sm'
spanNameInfoTxt.className =
'd-md-inline d-block name-info-txt ms-xxl-3 ms-md-3 mt-3 mt-ms-0'
spanNameInfoTxt.textContent = 'Dodaten avtor.'
spanNameInfoTxt.textContent = i18next.t('Dodaten avtor.')
divAuthor.appendChild(divSubjectName)
divSubjectName.appendChild(spanName)
@@ -594,9 +577,9 @@ function createNewAreaInput(pageForm) {
divSmallNameArea.className = 'author mt-4 added-field'
divSubjectName.className = 'subject-name'
spanInputNameTxtSlo.className = 'smaller-gray-uppercase'
spanInputNameTxtSlo.textContent = 'NOVO PODPODROČJE (slovensko)'
spanInputNameTxtSlo.textContent = i18next.t('NOVO PODPODROČJE (slovensko)')
spanInputNameTxtEng.className = 'smaller-gray-uppercase mt-4'
spanInputNameTxtEng.textContent = 'NOVO PODPODROČJE (angleško)'
spanInputNameTxtEng.textContent = i18next.t('NOVO PODPODROČJE (angleško)')
divRow.className = 'row align-items-center'
divRow2.className = 'row align-items-center'
divEnglishInput.className = 'mt-4'
@@ -617,11 +600,12 @@ function createNewAreaInput(pageForm) {
divColSm.className = 'col-sm mt-3 mt-sm-0'
divColSm2.className = 'col-sm mt-3 mt-sm-0'
spanNameInfoTxt.className = 'd-sm-inline name-info-txt ms-xxl-3 ms-md-3'
spanNameInfoTxt.textContent =
spanNameInfoTxt.textContent = i18next.t(
'Vpišite novo podpodročje. Na seznamu podpodročij bo vidno takoj po potrditvi administratorja portala.'
)
spanNameInfoTxtEng.className =
'd-sm-inline name-info-txt ms-xxl-3 ms-md-3 mt-4'
spanNameInfoTxtEng.textContent = 'Novo podpodročje (angleško).'
spanNameInfoTxtEng.textContent = i18next.t('Novo podpodročje (angleško).')
divSmallNameArea.appendChild(divSubjectName)
divSubjectName.appendChild(spanInputNameTxtSlo)
@@ -782,7 +766,7 @@ function handleAreasClick({ target }) {
const newButtonGroup = document.createElement('div')
const cancelButton = document.createElement('button')
const saveButton = document.createElement('button')
cancelButton.textContent = 'Prekliči'
cancelButton.textContent = i18next.t('Prekliči')
cancelButton.type = 'button'
cancelButton.className = 'btn btn-secondary me-2'
cancelButton.style.height = '33px'
@@ -790,7 +774,7 @@ function handleAreasClick({ target }) {
cancelButton.addEventListener('click', () =>
abortEditing(newButtonGroup, tableButtons, tDataArea, tDataTranslation)
)
saveButton.textContent = 'POTRDI'
saveButton.textContent = i18next.t('POTRDI')
saveButton.type = 'button'
saveButton.className = 'btn btn-primary'
saveButton.style.height = '33px'
@@ -986,76 +970,12 @@ function mobileMoveContent() {
currentPagePath.includes('slovarji') &&
!currentPagePath.includes('admin')
)
navTitle.textContent = 'Urejanje'
else navTitle.textContent = 'Administrator'
navTitle.textContent = i18next.t('Urejanje')
else navTitle.textContent = i18next.t('Administracija')
siteHeading.style.display = 'block'
}
}
function changePreview() {
const switchDomainLabel = document.getElementById('domain-labels')
const switchLabel = document.getElementById('label-checkbox')
const switchDefinition = document.getElementById('definition-check-box')
const switchSynonym = document.getElementById('synonyms')
const switchLink = document.getElementById('links')
const switchForeignLang = document.getElementById('language-group')
const switchForeignTerm = document.getElementById('termin-language-subgroup')
const switchForeignDef = document.getElementById(
'definition-language-subgroup'
)
const switchForeignSyn = document.getElementById('synonym-language-subgroup')
const switchImage = document.getElementById('images')
const switchAudio = document.getElementById('audio')
const switchVideo = document.getElementById('video')
const previewDomainSecondary = document.querySelector(
'.preview-domain-secondary'
)
const selectedLabel = document.querySelector('.preview-label')
const selectedDef = document.querySelector('.preview-definition')
const selectedSynonyms = document.querySelector('.preview-synonym')
const linkedTerms = document.getElementById('linked-terms')
const foreignLanguages = document.querySelector(
'.preview-languages-container'
)
const listForeignTerm = document.querySelector('.preview-f-term')
const listForeignDefinitions = document.querySelector(
'.preview-foreign-definition'
)
const foreignSynonyms = document.querySelector('.preview-foreign-synonyms')
const selectedImages = document.querySelector('.preview-images')
const selectedAudio = document.querySelector('.preview-audio')
const selectedVideo = document.querySelector('.preview-video')
if (!switchDomainLabel.checked)
previewDomainSecondary.classList.add('hide-preview')
else previewDomainSecondary.classList.remove('hide-preview')
if (!switchLabel.checked) selectedLabel.classList.add('hide-preview')
else selectedLabel.classList.remove('hide-preview')
if (!switchDefinition.checked) selectedDef.classList.add('hide-preview')
else selectedDef.classList.remove('hide-preview')
if (!switchSynonym.checked) selectedSynonyms.classList.add('hide-preview')
else selectedSynonyms.classList.remove('hide-preview')
if (!switchLink.checked) linkedTerms.classList.add('hide-preview')
else linkedTerms.classList.remove('hide-preview')
if (!switchForeignLang.checked) foreignLanguages.classList.add('hide-preview')
else foreignLanguages.classList.remove('hide-preview')
if (!switchForeignSyn.checked) foreignSynonyms.classList.add('hide-preview')
else foreignSynonyms.classList.remove('hide-preview')
if (!switchForeignTerm.checked) listForeignTerm.classList.add('hide-preview')
else listForeignTerm.classList.remove('hide-preview')
if (!switchForeignDef.checked)
listForeignDefinitions.classList.add('hide-preview')
else listForeignDefinitions.classList.remove('hide-preview')
if (!switchImage.checked) selectedImages.classList.add('hide-preview')
else selectedImages.classList.remove('hide-preview')
if (!switchAudio.checked) selectedAudio.classList.add('hide-preview')
else selectedAudio.classList.remove('hide-preview')
if (!switchVideo.checked) selectedVideo.classList.add('hide-preview')
else selectedVideo.classList.remove('hide-preview')
}
function checkUserRightsCb(el) {
const { terminologyReviewCb, languageReviewCb } = window.adminElements
const termRevCbs = document.querySelectorAll('.terminology-review-cb')
@@ -1109,12 +1029,18 @@ function ifUserExists(data, type) {
}
}
if (bool === true && data[0] !== undefined) {
modalText.textContent = `Uporabnik ${data[0].username} je že v tabeli.`
// modalText.textContent = `Uporabnik ${data[0].username} je že v tabeli.`
modalText.textContent =
i18next.t('Uporabnik') +
`${data[0].username}` +
i18next.t('je že v tabeli.')
modalEl.toggle()
} else createNewUserArea(data, type)
} else createNewUserArea(data, type)
} else {
modalText.textContent = `Preverite, če ste pravilno vpisali uporabniško ime. Bodite pozorni na velike in male črke.`
modalText.textContent = i18next.t(
'Preverite, če ste pravilno vpisali uporabniško ime. Bodite pozorni na velike in male črke.'
)
modalEl.toggle()
}
}
@@ -1172,24 +1098,24 @@ function createNewUserArea(data, type) {
inputConsultAdmin.type = 'checkbox'
if (type === 'portal') {
tdPortAdminOrAdmin.dataset.label = 'Skrbnik portala'
tdPortAdminOrAdmin.dataset.label = i18next.t('Skrbnik portala')
inputPortAdminOrAdmin.name = `rolesPerUser['${data[0].id}'][isPortalAdmin]`
tdDictAdmin.dataset.label = 'Skrbnik slovarjev'
tdDictAdmin.dataset.label = i18next.t('Skrbnik slovarjev')
inputDictAdmin.name = `rolesPerUser['${data[0].id}'][isDictionariesAdmin]`
tdConsultAdmin.dataset.label = 'Skrbnik svetovalnice'
tdConsultAdmin.dataset.label = i18next.t('Skrbnik svetovalnice')
inputConsultAdmin.name = `rolesPerUser['${data[0].id}'][isConsultancyAdmin]`
} else {
tdPortAdminOrAdmin.dataset.label = 'Administrator'
tdPortAdminOrAdmin.dataset.label = i18next.t('Administrator')
inputPortAdminOrAdmin.classList.add('administration-cb')
inputPortAdminOrAdmin.name = `rightsPerUser['${data[0].id}'][isAdministration]`
tdDictAdmin.dataset.label = 'Urejanje'
tdDictAdmin.dataset.label = i18next.t('Urejanje')
inputDictAdmin.name = `rightsPerUser['${data[0].id}'][isEditing]`
inputDictAdmin.classList.add('edit-cb')
tdConsultAdmin.dataset.label = 'Strokovni pregled'
tdConsultAdmin.dataset.label = i18next.t('Strokovni pregled')
inputConsultAdmin.classList.add('terminology-review-cb')
inputConsultAdmin.name = `rightsPerUser['${data[0].id}'][isTerminologyReview]`
tdLanguageRev.className = 'pt-1 pb-1'
tdLanguageRev.dataset.label = 'Jezikovni pregled'
tdLanguageRev.dataset.label = i18next.t('Jezikovni pregled')
divLanguageRev.className =
'form-check d-flex justify-content-left justify-content-xl-center'
inputLanguageRev.className = 'language-review-cb form-check-input'
@@ -1235,7 +1161,7 @@ function createNewUserArea(data, type) {
// Summernote
$('.summernote').summernote({
placeholder: 'Na kratko opišite zasnovo in namen slovarja.',
placeholder: i18next.t('Na kratko opišite zasnovo in namen slovarja.'),
height: 300,
minheight: 150,
toolbar: [
@@ -4,21 +4,28 @@
const commentsContainer = document.querySelector('#comments-container')
const dropImage = document.querySelector('#dropImage')
const commentCount = document.querySelector('#comments-count')
const collapsableHR = document.querySelector('.collapable-hr')
const hide = () => {
pager.className += ' d-none'
pager.className += ' invisible'
commentsContainer.className += ' d-none'
commentCount.className += ' d-none'
commentCount.className += ' invisible'
collapsableHR.className += ' d-none'
}
const show = () => {
pager.className = 'pager d-flex'
commentsContainer.className = 'comments-container pe-1'
dropImage.src = '/images/arrow_drop_up.svg'
commentCount.className = 'comment-count d-flex ms-auto me-4 text-p875rem'
collapsableHR.className += 'comments-top-hr mt-3'
}
document.getElementById('collapseComments').addEventListener('click', e => {
isVisible = !isVisible
if (isVisible) {
pager.className = 'pager'
commentsContainer.className = 'comments-container pe-1'
dropImage.src = '/images/arrow_drop_up.svg'
commentCount.className = 'comment-count d-flex ms-auto me-4 text-p875rem'
show()
} else {
dropImage.src = '/images/arrow_drop_down.svg'
hide()
+10 -9
View File
@@ -1,6 +1,6 @@
// TODO Remove no-console ignore rule once things are out of rapid dev phase.
/* eslint no-console: 0 */
/* global axios, initPagination */
/* global axios, initPagination, i18next */
const pageURL = location.pathname
window.addEventListener('load', () => {
@@ -127,20 +127,21 @@ function renderCommentCount(commentCount) {
let displayText = `${commentCount} `
// TODO Let a i18n library handle the following logic.
// TODO I18n
switch (commentCount % 100) {
case 1:
displayText += 'komentar'
displayText += i18next.t('komentar')
break
case 2:
displayText += 'komentarja'
displayText += i18next.t('komentarja')
break
case 3:
case 4:
displayText += 'komentarji'
displayText += i18next.t('komentarji')
break
default:
displayText += 'komentarjev'
displayText += i18next.t('komentarjev')
break
}
@@ -309,7 +310,7 @@ function submitComment() {
let ctxId = null
if (ctxData.ctxId !== undefined) ctxId = ctxData.ctxId
if (!message) {
alert('Vaš komentar je brez vsebine.')
alert(i18next.t('Vaš komentar je brez vsebine.'))
} else {
const payload = { message, ctxType, ctxId, quoteId: null }
createComment(payload)
@@ -326,7 +327,7 @@ function submitCommentReply() {
let ctxId = null
if (ctxData.ctxId !== undefined) ctxId = ctxData.ctxId
if (!message) {
alert('Vaš komentar je brez vsebine.')
alert(i18next.t('Vaš komentar je brez vsebine.'))
} else {
const payload = { message, ctxType, ctxId, quoteId }
createComment(payload)
@@ -577,11 +578,11 @@ async function onPageChange(newPage) {
const { page, numberOfAllPages } = await displayComments(newPage)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
@@ -11,6 +11,7 @@ function routeConsultancy(searchString) {
} else {
url = new URL(location)
url.searchParams.delete('p')
const sq = document.getElementById('search-query')
if (sq) {
url.searchParams.set('q', sq.value)
@@ -65,3 +66,14 @@ if (inputMainSearch) {
propagateFunctionalityToASearchButton(searchButton)
propagateFunctionalityToASearchButton(advancedSearchButton)
$(document).ready(() => {
const focused = $('#description')
if (focused) {
focused.focus()
}
if (window.location.pathname === '/svetovanje/iskanje') {
// todo
}
})
+273 -8
View File
@@ -1,4 +1,5 @@
/* global $, handleDomainsClickForConsultancy, inputFieldsChecker, currentPagePath, axios, nthParent, tooltipListWOL, tooltipTriggerList */
/* global $, bootstrap, handleDomainsClickForConsultancy, initPagination, inputFieldsChecker, currentPagePath,
axios, nthParent, tooltipListWOL, tooltipTriggerList, removeAllChildNodes, i18next */
/*
author: Miha Stele, 2022
@@ -9,6 +10,10 @@ let selectedID = -1
// consultancy FORM
let offsetMain
let OFFSET_PADDING_MASK = 16
if (window.location.pathname === '/svetovanje/vprasanje/admin/svetovalci') {
OFFSET_PADDING_MASK = 0
}
function adjustOffsetBy() {
offsetMain = document.querySelector('#offset-main')
const fixedTopSection = document.querySelector('#fixed-top-section')
@@ -22,15 +27,21 @@ function adjustOffsetBy() {
if (offsetHeaderPadding !== null) offsetMain.style.paddingTop = `0px`
} else {
for (let i = 0; i < offsetHeader.length; i++) {
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
offsetHeader[i].style.paddingTop = `${
referenceHeight - OFFSET_PADDING_MASK
}px`
}
if (headerPadding !== null) {
const headerPaddingHeight = headerPadding.offsetHeight
offsetMain.style.paddingTop = `${headerPaddingHeight}px`
offsetMain.style.paddingTop = `${
headerPaddingHeight - OFFSET_PADDING_MASK
}px`
}
if (offsetHeaderPadding !== null) {
const offsetHeaderHeight = offsetHeaderPadding.offsetHeight
offsetMain.style.paddingTop = `${referenceHeight + offsetHeaderHeight}px`
offsetMain.style.paddingTop = `${
referenceHeight + offsetHeaderHeight - OFFSET_PADDING_MASK
}px`
}
}
}
@@ -46,7 +57,7 @@ window.addEventListener('load', () => {
window.adminElements = ce
/* copy source admin.js in case of refactoring */
if (currentPagePath === '/svetovanje/vprasanje/admin/uporabniki') {
if (currentPagePath === '/svetovanje/vprasanje/admin/svetovalci') {
offsetMain.addEventListener('click', handleDomainsClickForConsultancy)
ce.name = document.getElementById('name-input')
if (ce.name) {
@@ -108,7 +119,7 @@ try {
const summernote = $('.summernote')
if (summernote) {
summernote.summernote({
placeholder: 'Na kratko opišite zasnovo in namen slovarja.',
placeholder: i18next.t('Na kratko opišite zasnovo in namen slovarja.'),
height: 300,
minheight: 150,
toolbar: [
@@ -383,7 +394,17 @@ if (createAnswerForm) {
// console.log(data)
if (res.status === 201) {
window.location.href = '/svetovanje'
const infoModal = document.getElementById('begin-response')
if (infoModal) {
const responseModal = new bootstrap.Modal(infoModal)
responseModal.toggle()
}
document
.getElementById('understand-btn')
.addEventListener('click', () => {
window.location.href = '/svetovanje'
})
}
}
@@ -407,7 +428,7 @@ if (insertConsultantForm) {
})
.then(result => {
console.log(result)
window.location.href = '/svetovanje/vprasanje/admin/uporabniki'
window.location.href = '/svetovanje/vprasanje/admin/svetovalci'
})
})
}
@@ -421,6 +442,243 @@ try {
console.log(e)
}
/// Frontend Pagination (as in other pages in this project)
function onResultClick(e) {
const entryEl = e.target.closest(`#${this.id} a.rl`)
if (!entryEl) return
const anchorId = entryEl.querySelector('.anchor').id
const anchoredUrl = new URL(location)
anchoredUrl.hash = anchorId
history.replaceState(null, '', anchoredUrl)
}
const resultsListEl = document.getElementById('results-data')
if (resultsListEl) {
resultsListEl.addEventListener('click', onResultClick)
}
const initialPage = +new URL(location).searchParams.get('p') || 1
let updatePager
try {
updatePager = initPagination('pagination', onPageChange, initialPage)
} catch (e) {}
async function onPageChange(newPage) {
const receivedPageNumber = await changePage(newPage)
updateUrlAndHistory(receivedPageNumber)
}
async function changePage(newPage) {
try {
const res = await getDataForPage(newPage)
const page = +res.headers.page
const numberOfAllPages = +res.headers['number-of-all-pages']
const resultsMarkup = res.data
removeAllChildNodes(resultsListEl)
renderResults(resultsMarkup)
updatePager(page, numberOfAllPages)
return page
} catch (error) {
// console.log(error)
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
return // return to bypass error caused (assumed) by popstate on iOS/MacOS
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
}
}
async function getDataForPage(page) {
const qParams = new URL(location).searchParams
qParams.set('p', page)
// const url = `/api/v1/search/main?${qParams}`
// let url = `/api/v1/consultancy/entry-pagination?${qParams}`
// URL PATTERN PARSING
const PATH = window.location.pathname
if (PATH.includes('/admin/')) {
// todo ADMIN URL handling
qParams.set('isAdmin', 'true')
// url = `/api/v1/consultancy/entry-pagination?${qParams}` // required due to updated queryParams
if (PATH.includes('/novo')) {
qParams.set('type', 'new')
} else if (PATH.includes('/pripravljeno')) {
qParams.set('type', 'review')
} else if (PATH.includes('/zavrnjeno')) {
qParams.set('type', 'rejected')
} else if (PATH.includes('/v-delu')) {
qParams.set('type', 'in progress')
} else if (PATH.includes('/objavljeno')) {
qParams.set('type', 'published')
} else {
// Invalid case
console.log('INVALID CASE, CHECK URL')
return
}
}
// const url = `/api/v1/search/main?${qParams}`
const url = `/api/v1/consultancy/entry-pagination?${qParams}`
console.log(url)
return await axios.get(url)
}
function renderResults(resultsMarkup) {
const wrapper = document.createElement('div')
wrapper.innerHTML = resultsMarkup
resultsListEl.appendChild(wrapper)
}
function updateUrlAndHistory(page) {
const newUrl = new URL(location)
newUrl.searchParams.set('p', page)
history.pushState(null, '', newUrl)
}
window.addEventListener('popstate', () => {
const page = +new URL(location).searchParams.get('p') || 1
changePage(page)
})
/// // PAGINATION (backend only) /////
/* const updatePager = initPaginationBE('pagination', onPageChangeBE)
function onPageChangeBE(newPage) {
const newUrl = new URL(location)
newUrl.searchParams.set('p', newPage)
history.pushState(null, '', newUrl)
window.location.href = newUrl
}
function initPaginationBE(paginationRootElId, onPageChange, currentPage = 1) {
const rootEl = document.getElementById(paginationRootElId)
const btnFirstPage = rootEl.querySelector('.first-page')
const btnPreviousPage = rootEl.querySelector('.previous-page')
const btnNextPage = rootEl.querySelector('.next-page')
const btnLastPage = rootEl.querySelector('.last-page')
const formEl = rootEl.querySelector('form')
const pageInputEl = formEl.querySelector('input')
const pagesCountDisplayEl = formEl.querySelector('.pages-total')
let reqLock = false
rootEl.addEventListener('click', handleButtonClick)
formEl.addEventListener('submit', handleFormSubmit)
function handleButtonClick({ target }) {
if (reqLock) return
const buttonEl = target.closest(`#${paginationRootElId} button`)
if (!buttonEl) return
const numOfAllPages = +pagesCountDisplayEl.textContent
if (buttonEl.classList.contains('first-page')) {
if (currentPage === 1) return
enableLock()
onPageChange(1)
} else if (buttonEl.classList.contains('previous-page')) {
if (currentPage === 1) return
enableLock()
onPageChange(currentPage - 1)
} else if (buttonEl.classList.contains('next-page')) {
if (currentPage === numOfAllPages) return
enableLock()
onPageChange(currentPage + 1)
} else if (buttonEl.classList.contains('last-page')) {
if (currentPage === numOfAllPages) return
enableLock()
onPageChange(numOfAllPages)
}
}
function handleFormSubmit(e) {
e.preventDefault()
if (reqLock) return
const inputValue = +pageInputEl.value
if (!(inputValue > 0 && inputValue <= pagesCountDisplayEl.textContent)) {
alert('Nepravilna vrednost strani')
pageInputEl.value = currentPage
return
}
enableLock()
onPageChange(inputValue)
}
function enableLock() {
reqLock = true
btnFirstPage.disabled = true
btnPreviousPage.disabled = true
btnNextPage.disabled = true
btnLastPage.disabled = true
pageInputEl.disabled = true
}
function disableLock() {
reqLock = false
btnFirstPage.disabled = false
btnPreviousPage.disabled = false
btnNextPage.disabled = false
btnLastPage.disabled = false
pageInputEl.disabled = false
}
function updatePagerUi(newCurrentPage, newNumOfAllPages) {
disableLock()
if (!newCurrentPage) return
currentPage = newCurrentPage
pageInputEl.value = newCurrentPage
pagesCountDisplayEl.textContent = newNumOfAllPages
if (newCurrentPage === 1) {
btnFirstPage.disabled = true
btnPreviousPage.disabled = true
} else {
btnFirstPage.disabled = false
btnPreviousPage.disabled = false
}
if (newCurrentPage === newNumOfAllPages) {
btnNextPage.disabled = true
btnLastPage.disabled = true
} else {
btnNextPage.disabled = false
btnLastPage.disabled = false
}
}
updatePagerUi(
+new URL(location).searchParams.get('p') || 1,
+document.querySelector('.pages-total').innerHTML
)
return updatePagerUi
}
window.addEventListener('popstate', () => {
const page = +new URL(location).searchParams.get('p') || 1
onPageChangeBE(page)
})
*/
/// ///////////////////
/*
if (tooltipList) {
console.log(tooltipList)
@@ -438,3 +696,10 @@ $(document).ready(() => {
focused.focus()
}
})
const askBackButton = document.querySelector('#cancel-cons-btn')
if (askBackButton) {
askBackButton.addEventListener('click', () => {
history.back()
})
}
+53 -37
View File
@@ -7,9 +7,15 @@
// Paginacijo inicializiraš s klicem funkcije initPagination:
// 1. parameter: id pager elementa. V demo-paginacija.pug je to #pagination.
// UPDATE: Sedaj sprejme tudi array idjev, če je pager kontrolerjev več (npr. en zgoraj (#pagination-top), en spodaj (#pagination-bottom)).
// 2. parameter: callback funkcijo, ki jo pager pokliče vsakič, ko uporabnik zahteva novo stran. Poliče jo s številko zahtevane strani.
// vrnjena vrednost: funkcija, ki jo (kasneje) kličeš za posodobitev pagerja. Tu jo poimenujem updateDemoPager.
const updateDemoPager = initPagination('pagination', onPageChange)
const updateDemoPager = initPagination(
['pagination-top', 'pagination-bottom'],
onPageChange
)
// Za samo en kontroler je bilo:
// const updateDemoPager = initPagination('pagination', onPageChange)
// Fukncija, prejme številko nove strani in naj:
// 1. Pridobi podatke nove strani.
@@ -62,27 +68,49 @@
* Na vsaki strani, kjer bo paginacija, jo inicializiraj in uporabljaj po zgledu zgornje kode. *
\** ****************************************************************************************************************************************** **/
function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
const rootEl = document.getElementById(paginationRootElId)
const btnFirstPage = rootEl.querySelector('.first-page')
const btnPreviousPage = rootEl.querySelector('.previous-page')
const btnNextPage = rootEl.querySelector('.next-page')
const btnLastPage = rootEl.querySelector('.last-page')
const formEl = rootEl.querySelector('form')
const pageInputEl = formEl.querySelector('input')
const pagesCountDisplayEl = formEl.querySelector('.pages-total')
function initPagination(paginationRootElIds, onPageChange, currentPage = 1) {
let reqLock = false
let numOfAllPages
const backwardBtnEls = []
const forwardBtnEls = []
const pageInputEls = []
const pagesCountDisplayEls = []
rootEl.addEventListener('click', handleButtonClick)
formEl.addEventListener('submit', handleFormSubmit)
if (Array.isArray(paginationRootElIds)) {
paginationRootElIds.forEach(id => initControls(id))
} else {
initControls(paginationRootElIds)
}
const allControlEls = [...backwardBtnEls, ...forwardBtnEls, ...pageInputEls]
function handleButtonClick({ target }) {
function initControls(paginationRootElId) {
const rootEl = document.getElementById(paginationRootElId)
const btnFirstPage = rootEl.querySelector('.first-page')
const btnPreviousPage = rootEl.querySelector('.previous-page')
const btnNextPage = rootEl.querySelector('.next-page')
const btnLastPage = rootEl.querySelector('.last-page')
const formEl = rootEl.querySelector('form')
const pageInputEl = formEl.querySelector('input')
const pagesCountDisplayEl = formEl.querySelector('.pages-total')
numOfAllPages = +pagesCountDisplayEl.textContent
backwardBtnEls.push(btnFirstPage, btnPreviousPage)
forwardBtnEls.push(btnNextPage, btnLastPage)
pageInputEls.push(pageInputEl)
pagesCountDisplayEls.push(pagesCountDisplayEl)
rootEl.addEventListener('click', e => {
handleButtonClick(e, paginationRootElId)
})
formEl.addEventListener('submit', e => handleFormSubmit(e, pageInputEl))
}
function handleButtonClick({ target }, paginationRootElId) {
if (reqLock) return
const buttonEl = target.closest(`#${paginationRootElId} button`)
if (!buttonEl) return
const numOfAllPages = +pagesCountDisplayEl.textContent
if (buttonEl.classList.contains('first-page')) {
if (currentPage === 1) return
@@ -103,12 +131,12 @@ function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
}
}
function handleFormSubmit(e) {
function handleFormSubmit(e, pageInputEl) {
e.preventDefault()
if (reqLock) return
const inputValue = +pageInputEl.value
if (!(inputValue > 0 && inputValue <= pagesCountDisplayEl.textContent)) {
if (!(inputValue > 0 && inputValue <= numOfAllPages)) {
alert('Nepravilna vrednost strani')
pageInputEl.value = currentPage
return
@@ -120,20 +148,12 @@ function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
function enableLock() {
reqLock = true
btnFirstPage.disabled = true
btnPreviousPage.disabled = true
btnNextPage.disabled = true
btnLastPage.disabled = true
pageInputEl.disabled = true
allControlEls.forEach(el => (el.disabled = true))
}
function disableLock() {
reqLock = false
btnFirstPage.disabled = false
btnPreviousPage.disabled = false
btnNextPage.disabled = false
btnLastPage.disabled = false
pageInputEl.disabled = false
allControlEls.forEach(el => (el.disabled = false))
}
function updatePagerUi(newCurrentPage, newNumOfAllPages) {
@@ -141,23 +161,19 @@ function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
if (!newCurrentPage) return
currentPage = newCurrentPage
pageInputEl.value = newCurrentPage
pagesCountDisplayEl.textContent = newNumOfAllPages
pageInputEls.forEach(el => (el.value = newCurrentPage))
pagesCountDisplayEls.forEach(el => (el.textContent = newNumOfAllPages))
if (newCurrentPage === 1) {
btnFirstPage.disabled = true
btnPreviousPage.disabled = true
backwardBtnEls.forEach(el => (el.disabled = true))
} else {
btnFirstPage.disabled = false
btnPreviousPage.disabled = false
backwardBtnEls.forEach(el => (el.disabled = false))
}
if (newCurrentPage === newNumOfAllPages) {
btnNextPage.disabled = true
btnLastPage.disabled = true
forwardBtnEls.forEach(el => (el.disabled = true))
} else {
btnNextPage.disabled = false
btnLastPage.disabled = false
forwardBtnEls.forEach(el => (el.disabled = false))
}
}
+377 -147
View File
@@ -1,4 +1,4 @@
/* global $, axios, bootstrap, currentPagePath, initPagination, removeAllChildNodes, unsavedData */
/* global $, axios, bootstrap, currentPagePath, initPagination, removeAllChildNodes, unsavedData, replaceContainer, i18next */
// Temporary workaround (use of currentPagePath).
@@ -6,6 +6,8 @@ window.addEventListener('load', () => {
initDictionaries()
})
let queryBattery = ''
function initDictionaries() {
const ce = {}
window.dictionaryElements = ce
@@ -166,7 +168,7 @@ function initDictionaries() {
if (ce.fileUploadInput.files.item(0) !== null)
chosenFile.textContent = ce.fileUploadInput.files.item(0).name
else {
chosenFile.textContent = 'Izberi datoteko'
chosenFile.textContent = i18next.t('Izberi datoteko')
}
}
})
@@ -185,12 +187,140 @@ function initDictionaries() {
await axios.post(event.target.action, payload)
alert('SLOVAR UVOŽEN')
alert(i18next.t('SLOVAR UVOŽEN'))
} catch (error) {
alert('NAPAKA V UVOZU')
alert(i18next.t('NAPAKA V UVOZU'))
}
}
{
const resultsListEl = document.getElementById('page-results')
const dictionaryId = document.getElementById('dictionary-id').value
const updatePager = initPagination('pagination', onPageChange)
async function onPageChange(newPage) {
try {
const { page, numberOfAllPages, results } = await getDataForPage(
newPage
)
removeAllChildNodes(resultsListEl)
renderResults(results)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
}
}
async function getDataForPage(page) {
const url = `/api/v1/dictionaries/${dictionaryId}/showImportFromFileForm?p=${page}`
const { data } = await axios.get(url)
return data
}
function renderResults(results) {
const localeOptions = {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
}
results.forEach(result => {
const rowEl = document.createElement('tr')
const td1 = document.createElement('td')
const td2 = document.createElement('td')
const td3 = document.createElement('td')
const td4 = document.createElement('td')
const date = new Date(result.time_started).toLocaleDateString(
'sl-SL',
localeOptions
)
td1.textContent = date
td2.textContent = result.file_format
td3.textContent = result.count_valid_entries
td4.textContent = result.status
rowEl.append(td1, td2, td3, td4)
resultsListEl.appendChild(rowEl)
})
}
}
}
if (/\/slovarji\/\d+\/izvoz/.test(currentPagePath)) {
const resultsListEl = document.getElementById('page-results')
const dictionaryId = document.getElementById('dictionary-id').value
const updatePager = initPagination('pagination', onPageChange)
async function onPageChange(newPage) {
try {
const { page, numberOfAllPages, results } = await getDataForPage(
newPage
)
removeAllChildNodes(resultsListEl)
renderResults(results)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
}
}
async function getDataForPage(page) {
const url = `/api/v1/dictionaries/${dictionaryId}/showExportToFileForm?p=${page}`
const { data } = await axios.get(url)
return data
}
function renderResults(results) {
const localeOptions = {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
}
results.forEach(result => {
const rowEl = document.createElement('tr')
const td1 = document.createElement('td')
const td2 = document.createElement('td')
const td3 = document.createElement('td')
const td4 = document.createElement('td')
const date = new Date(result.time_created).toLocaleDateString(
'sl-SL',
localeOptions
)
td1.textContent = date
td2.textContent = result.export_file_format
td3.textContent = result.entry_count
if (result.status === 'finished') {
const aEl = document.createElement('a')
aEl.href = `/slovarji/export-download/${result.id}`
aEl.textContent = i18next.t('Shrani')
aEl.className = 'btn btn-primary'
td4.append(aEl)
} else td4.textContent = ''
rowEl.append(td1, td2, td3, td4)
resultsListEl.appendChild(rowEl)
})
}
}
if (/\/slovarji\/\d+\/vsebina/.test(currentPagePath)) {
ce.formEditContent = document.getElementById('form-edit-content')
ce.formEditContent.addEventListener('submit', updateEntry)
@@ -233,6 +363,7 @@ function initDictionaries() {
ce.clearSearchInput = document.querySelector('.clear-search-input')
ce.collapsablePart = document.querySelectorAll('.collapsable-entry-part')
ce.scrollEl = document.querySelector('.content-nav-content')
$('.multiple').on('select2:select', enableButton)
ce.collapsablePart.forEach(el => {
el.addEventListener('hide.bs.collapse', () =>
changePageContent('collapse-hidden')
@@ -257,7 +388,7 @@ function initDictionaries() {
})
ce.statusEditEl = document.getElementById('status-edit')
// ce.deleteEntryBtn.addEventListener('click', () => ajaxDeleteEntry())
ce.newEntryBtn.addEventListener('click', () => {
ce.newEntryBtn.addEventListener('click', e => {
ce.formEditContent.reset()
changePageContent('new-entry-btn')
})
@@ -307,7 +438,8 @@ function initDictionaries() {
if (mcBtnsGrp.length) {
mcBtnsGrp.forEach(e => e.addEventListener('click', enableButton))
}
ce.newHeadwordGroupBtn.addEventListener('click', createHeadword)
if (ce.newHeadwordGroupBtn)
ce.newHeadwordGroupBtn.addEventListener('click', createHeadword)
if (ce.newConnectionBtn)
ce.newConnectionBtn.addEventListener('click', () =>
addConnectionField(ce.formEditContent, ce.newConnectionBtn)
@@ -408,7 +540,7 @@ function initDictionaries() {
if (termListMenu.childElementCount > 1) {
const termListLabels = termListMenu.querySelectorAll('label')
termListLabels[0].click()
if (termListLabels.length) termListLabels[0].click()
}
function handleClick({ target }) {
@@ -423,10 +555,11 @@ function initDictionaries() {
const okBtnText = modalUseBtn.textContent
const cnclBtnTxt = modalCnclBtn.textContent
const modalMainTxt = modalMain.textContent
modalUseBtn.textContent = 'Shrani'
modalCnclBtn.textContent = 'Ne shrani'
modalMain.textContent =
modalUseBtn.textContent = i18next.t('Shrani')
modalCnclBtn.textContent = i18next.t('Ne shrani')
modalMain.textContent = i18next.t(
'Imate neshranjene spremembe. Ali jih želite shraniti?'
)
const alertModal = new bootstrap.Modal(
document.getElementById('alert-modal')
)
@@ -478,8 +611,8 @@ function initDictionaries() {
if (deleteEntryEl) {
const modalUseBtn = document.getElementById('modal-del-btn')
const modalCnclBtn = document.getElementById('cancel-btn')
modalUseBtn.textContent = 'Izbriši'
modalCnclBtn.textContent = 'Ne izbriši'
modalUseBtn.textContent = i18next.t('Izbriši')
modalCnclBtn.textContent = i18next.t('Ne izbriši')
const alertModal = new bootstrap.Modal(
document.getElementById('delete-modal')
)
@@ -497,8 +630,8 @@ function initDictionaries() {
const { data } = await axios.get(
`/api/v1/entries/${entryId}/version-snapshots/${versionId}`
)
const payload = { entry: data }
insertTermData(entryId, payload)
const payload = { entry: data.data }
insertTermData(entryId, payload, data.author)
const isPublishedEl = payload.entry.is_published
const info = new FormData(formEditContent)
info.append('isPublishedEl', isPublishedEl)
@@ -531,6 +664,7 @@ function initDictionaries() {
info.append('isPublishedEl', isPublishedEl)
loadPreview(info)
changeVersionList(data.entry.versions)
setLatestVersion(data.entry)
ce.formEditContent.addEventListener('input', () => (unsaved = true))
formEditContent.dataset.entryId = entryId
formEditContent.action = '/api/v1/entries/update'
@@ -553,7 +687,7 @@ function initDictionaries() {
}
}
function insertTermData(entryId, data) {
function insertTermData(entryId, data, vAuthor) {
const { newConnectionBtn } = window.dictionaryElements
const localeOptions = {
day: '2-digit',
@@ -609,12 +743,20 @@ function initDictionaries() {
}
else
for (let i = 0; i < termIdText.length; i++) {
termIdText[i].textContent = `ID: Ni idja`
termIdText[i].textContent = i18next.t('ID: Ni idja')
}
ce.authorEl.textContent = data.entry.version_author
ce.versionEl.textContent = `Verzija ${data.entry.version}`
ce.previewVersion.textContent = `Verzija ${data.entry.version}`
ce.previewAuthor.textContent = data.entry.version_author
if (vAuthor) {
ce.authorEl.textContent = vAuthor
ce.previewAuthor.textContent = vAuthor
} else {
ce.authorEl.textContent = data.entry.version_author
ce.previewAuthor.textContent = data.entry.version_author
}
// ce.versionEl.textContent = `Verzija ${data.entry.version}`
ce.versionEl.textContent = i18next.t('Verzija') + `${data.entry.version}`
// ce.previewVersion.textContent = `Verzija ${data.entry.version}`
ce.previewVersion.textContent =
i18next.t('Verzija') + `${data.entry.version}`
termName.value = data.entry.term
? data.entry.term.replace(/&quot;/g, '"')
: ''
@@ -757,18 +899,19 @@ function initDictionaries() {
const payload = new URLSearchParams(new FormData(ce.formEditContent))
payload.set('entryId', entryId)
try {
saveBtn.textContent = i18next.t('Shranjujem ...')
await axios.post(ce.formEditContent.action, payload)
spinnerEl.classList.remove('d-none')
saveBtn.classList.add('saved-entry-btn')
saveBtn.textContent = 'Shranjeno'
saveBtn.textContent = i18next.t('Shranjeno')
if (id != null) entryId = id
ajaxSideMenu(entryId)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
messageContainer.textContent = message
}
@@ -776,19 +919,20 @@ function initDictionaries() {
event.preventDefault()
const payload = new URLSearchParams(new FormData(ce.formEditContent))
try {
saveBtn.textContent = i18next.t('Shranjujem ...')
const res = await axios.post(ce.formEditContent.action, payload)
spinnerEl.classList.remove('d-none')
saveBtn.classList.add('saved-entry-btn')
saveBtn.textContent = 'Shranjeno'
saveBtn.textContent = i18next.t('Shranjeno')
let entryId = res.data.entryId
if (id != null) entryId = id
ajaxSideMenu(entryId)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
messageContainer.textContent = message
} finally {
@@ -806,11 +950,11 @@ function initDictionaries() {
})
renderTerms(data, entryId)
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
messageContainer.textContent = message
}
@@ -829,7 +973,7 @@ function initDictionaries() {
selectNextEntry(selectedIndex)
} catch (error) {
console.log(error)
const message = 'Prišlo je do napake.'
const message = i18next.t('Prišlo je do napake.')
messageContainer.textContent = message
}
}
@@ -870,21 +1014,27 @@ function initDictionaries() {
/&quot;/g,
'"'
)}`
} else labelElement.textContent = '[ni termina]'
} else labelElement.textContent = '[ni termina]'
} else labelElement.textContent = i18next.t('[ni termina]')
} else labelElement.textContent = i18next.t('[ni termina]')
} else {
if (el.isValid) {
if (el.isPublished) {
labelElement.textContent = sloTerm
labelElement.textContent = `${sloTerm} ${
el.homonymSort ? '(' + el.homonymSort + ')' : ''
}`
labelElement.className =
'terms-label term-good-btn btn p-2 ms-2 me-3 text-truncate justify-content-start d-inline-block'
} else {
labelElement.className =
'terms-label btn p-2 ms-2 me-3 text-truncate justify-content-start d-inline-block'
labelElement.textContent = sloTerm
labelElement.textContent = `${sloTerm} ${
el.homonymSort ? '(' + el.homonymSort + ')' : ''
}`
}
} else {
labelElement.textContent = sloTerm
labelElement.textContent = `${sloTerm} ${
el.homonymSort ? '(' + el.homonymSort + ')' : ''
}`
labelElement.className =
'terms-label not-valid-not-published btn p-2 ms-2 me-3 text-truncate justify-content-start d-inline-block'
}
@@ -949,84 +1099,83 @@ function initDictionaries() {
}
}
{
const resultsListEl = document.getElementById('page-results')
const dictionaryId = document.getElementById('subareas-dict-id').value
const resultsListEl = document.getElementById('page-results')
const dictionaryId = document.getElementById('subareas-dict-id').value
const updatePager = initPagination('pagination', onPageChange)
const updatePager = initPagination('pagination', onPageChange)
async function onPageChange(newPage) {
try {
const { page, numberOfAllPages, results } = await getDataForPage(
newPage
)
removeAllChildNodes(resultsListEl)
renderResults(results)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = 'Prišlo je do napake.'
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
}
alert(message)
updatePager()
async function onPageChange(newPage) {
try {
const results = await getDataForPage(newPage)
const numberOfAllPages = +results.headers['number-of-all-pages']
const page = +results.headers.page
removeAllChildNodes(resultsListEl)
renderResults(results.data)
updatePager(page, numberOfAllPages)
} catch (error) {
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
}
async function getDataForPage(page) {
const url = `/api/v1/dictionaries/${dictionaryId}/listDomainLabels?p=${page}`
const { data } = await axios.get(url)
return data
}
function renderResults(results) {
results.forEach(result => {
const rowEl = document.createElement('tr')
const input = document.createElement('input')
const th = document.createElement('th')
const input2 = document.createElement('input')
const td1 = document.createElement('td')
const td2 = document.createElement('td')
const div = document.createElement('div')
const editBtn = document.createElement('button')
const deleteBtn = document.createElement('button')
const imgEditEl = document.createElement('img')
const imgDelEl = document.createElement('img')
input.value = result.id
input.type = 'hidden'
input.name = 'domainLabelId'
th.scope = 'row'
input2.className = 'form-check checkbox-table'
input2.type = 'checkbox'
input2.name = 'isVisible'
input2.disabled = true
input2.checked = !!result.isVisible
th.append(input2)
td1.className = 'tdata-area'
td1.textContent = result.name
td2.classList.add('buttons-group')
div.classList.add('table-buttons')
editBtn.className = 'p-0 table-button-grp me-3 edit-row-btn'
editBtn.type = 'button'
imgEditEl.src = '/images/u_edit-alt.svg'
deleteBtn.className = 'p-0 table-button-grp delete-row-btn'
deleteBtn.dataset.bsTarget = '#alert-modal'
deleteBtn.dataset.bsToggle = 'modal'
deleteBtn.type = 'button'
imgDelEl.src = '/images/red-trash-icon.svg'
td2.append(div)
div.append(editBtn, deleteBtn)
editBtn.append(imgEditEl)
deleteBtn.append(imgDelEl)
rowEl.append(input, th, td1, td2)
resultsListEl.appendChild(rowEl)
})
alert(message)
updatePager()
}
}
async function getDataForPage(page) {
// const url = `/api/v1/dictionaries/${dictionaryId}/listDomainLabels?p=${page}`
const url = `/api/v1/dictionaries/${dictionaryId}/domainLabels?q=${queryBattery}&p=${page}`
// const { data } = await axios.get(url)
return await axios.get(url)
}
function renderResults(results) {
replaceContainer('page-results', results)
}
const updatePaginationOnFilter = axiosResult => {
const numberOfAllPages = +axiosResult.headers['number-of-all-pages']
const page = +axiosResult.headers.page
// removeAllChildNodes(resultsListEl)
// renderResults(results.data)
// console.log(numberOfAllPages)
// console.log(page)
// console.log(updatePager)
updatePager(page, numberOfAllPages)
}
/// / Due to unsual design, the function was moved inside
function searchController() {
if (window.location.pathname.includes('podrocne-oznake')) {
queryBattery = document.getElementById('input-search').value
// console.log(queryBattery)
axios
.get(
`/api/v1/dictionaries/${
window.location.pathname.split('/')[2]
}/domainLabels?q=${queryBattery}&p=${1}`
)
.then(result => {
updatePaginationOnFilter(result)
replaceContainer('page-results', result.data)
})
}
}
const inlineSearchButton = document.getElementById('inline-search-btn')
if (inlineSearchButton) {
inlineSearchButton.addEventListener('click', searchController)
$('#input-search').on('keyup', function (e) {
if (e.code === 'Enter' || e.code === 'NumpadEnter') {
searchController()
}
})
}
/// //
}
if (/\/slovarji\/\d+\/napredno/.test(currentPagePath)) {
@@ -1217,8 +1366,8 @@ function mobileMoveContent() {
currentPagePath.includes('slovarji') &&
!currentPagePath.includes('admin')
)
navTitle.textContent = 'Urejanje'
else navTitle.textContent = 'Administrator'
navTitle.textContent = i18next.t('Urejanje')
else navTitle.textContent = i18next.t('Administracija')
siteHeading.style.display = 'block'
}
}
@@ -1310,9 +1459,9 @@ function createNewAreaInput(pageForm) {
divSmallNameArea.className = 'author mt-4 added-field'
divSubjectName.className = 'subject-name'
spanInputNameTxtSlo.className = 'input-name-txt'
spanInputNameTxtSlo.textContent = 'NOVO PODPODROČJE (slovensko)'
spanInputNameTxtSlo.textContent = i18next.t('NOVO PODPODROČJE (slovensko)')
spanInputNameTxtEng.className = 'input-name-txt mt-4'
spanInputNameTxtEng.textContent = 'NOVO PODPODROČJE (angleško)'
spanInputNameTxtEng.textContent = i18next.t('NOVO PODPODROČJE (angleško)')
divRow.className = 'row align-items-center'
divRow2.className = 'row align-items-center'
divEnglishInput.className = 'mt-4'
@@ -1333,11 +1482,12 @@ function createNewAreaInput(pageForm) {
divColSm.className = 'col-sm mt-3 mt-sm-0'
divColSm2.className = 'col-sm mt-3 mt-sm-0'
spanNameInfoTxt.className = 'd-sm-inline name-info-txt ms-xxl-3 ms-md-3'
spanNameInfoTxt.textContent =
spanNameInfoTxt.textContent = i18next.t(
'Vpišite novo podpodročje. Na seznamu podpodročij bo vidno takoj po potrditvi administratorja portala.'
)
spanNameInfoTxtEng.className =
'd-sm-inline name-info-txt ms-xxl-3 ms-md-3 mt-4'
spanNameInfoTxtEng.textContent = 'Novo podpodročje (angleško).'
spanNameInfoTxtEng.textContent = i18next.t('Novo podpodročje (angleško).')
divSmallNameArea.appendChild(divSubjectName)
divSubjectName.appendChild(spanInputNameTxtSlo)
@@ -1468,6 +1618,10 @@ function changePageContent(el) {
const collapsableBtn = document.querySelectorAll('.collapsable-entry-btn')
const addedFields = document.querySelectorAll('.added-field')
const collapsibleData = document.querySelectorAll('.collapsible-data')
const responseModal = new bootstrap.Modal(
document.getElementById('duplicate-modal'),
{ keyboard: false }
)
switch (el) {
case 'content-preview':
loadPreview(info)
@@ -1530,6 +1684,7 @@ function changePageContent(el) {
break
case 'new-entry-btn': {
// formEditContent.reset()
formEditContent.removeAttribute('data-entry-id')
formEditContent.action = '/api/v1/entries/create'
if (editSection.classList.contains('d-none'))
@@ -1546,6 +1701,16 @@ function changePageContent(el) {
previewBtnEl.disabled = true
delete newEntryBtn.dataset.term
}
// editBtnEl.click()
editBtnEl.classList.add('active-site-link')
previewBtnEl.classList.remove('active-site-link')
commentsBtnEl.classList.remove('active-site-link')
previewButtonsGroup.classList.remove('d-none')
commentsButtonsGroup.classList.add('d-none')
previewSection.classList.add('d-none')
editSection.classList.remove('d-none')
commentsSection.classList.add('d-none')
resizeFields.forEach(el => autoResize(el))
authorEl.textContent = ''
versionEl.textContent = 'Verzija 1'
previewAuthor.textContent = ''
@@ -1558,15 +1723,19 @@ function changePageContent(el) {
deleteEntry.disabled = true
changeCollapsedContent()
if (addedFields.length) addedFields.forEach(el => el.remove())
editBtnEl.click()
termInputField.focus()
const messageContainer = document.querySelectorAll('.message-container')
messageContainer.forEach(el => el.classList.add('d-none'))
window.scrollTo({ top: 0, behavior: 'smooth' })
selectedEntry.classList.remove('selected-term-btn')
$('.multiple').val(null).trigger('change')
$('.without-dropdown').val(null).trigger('change')
editBtnEl.click()
// editBtnEl.click()
// termInputField.addEventListener('focus', () =>
// showMCButtons(termInputField, 'link')
// )
termInputField.focus()
termInputField.click()
break
}
case 'first':
@@ -1610,7 +1779,6 @@ function changePageContent(el) {
commentsBtnEl.disabled = true
commentsBtnEl.classList.add('disabled')
showDates.disabled = true
duplicateEntry.disabled = true
deleteEntry.disabled = true
changeCollapsedContent()
editBtnEl.click()
@@ -1618,6 +1786,8 @@ function changePageContent(el) {
window.scrollTo({ top: 0, behavior: 'smooth' })
selectedEntry.classList.remove('selected-term-btn')
editBtnEl.click()
responseModal.toggle()
duplicateEntry.disabled = true
break
case 'true':
spanFilterText.classList.remove('normal-gray-label')
@@ -1798,8 +1968,9 @@ function loadPreview(info) {
: linksArr[i][key] === 'broader'
? 'BT:'
: ''
linkedTerms.innerHTML += keyTxt + ' ' + key + ' '
linkedTerms.innerHTML += keyTxt + ' ' + key
if (parseInt(i) !== linksArr.length - 1) linkedTerms.innerHTML += ', '
else linkedTerms.innerHTML += ' '
}
}
} else changeClasses(previewLinkedTerms, 'hide')
@@ -1924,6 +2095,7 @@ function changeVersionList(versions) {
dateLabel.dataset.bsCustomClass = 'dark-gray-tooltip'
dateLabel.dataset.bsPlacement = 'bottom'
dateLabel.dataset.bsToggle = 'tooltip'
dateLabel.dataset.bsHtml = 'true'
const date = new Date(el.version_time).toLocaleDateString(
'sl-SL',
localeOptions
@@ -1932,9 +2104,16 @@ function changeVersionList(versions) {
dateRadio.id = `date${el.version}`
dateRadio.value = `${el.version}`
dateLabel.htmlFor = `date${el.version}`
// new bootstrap.Tooltip(dateLabel, {
// title: `Verzija ${el.version} <br> Avtor: ${el.version_author}`
// })
// eslint-disable-next-line
new bootstrap.Tooltip(dateLabel, {
title: `Verzija ${el.version}`
title:
i18next.t('Verzija') +
`${el.version} <br>` +
i18next.t('Avtor:') +
`${el.version_author}`
})
allDatesEl.append(dateRadio)
allDatesEl.appendChild(dateLabel)
@@ -1942,6 +2121,30 @@ function changeVersionList(versions) {
}
}
function setLatestVersion(data) {
const latestVersionLabel = document.getElementById('latest-version-label')
// const tooltip = new bootstrap.Tooltip(latestVersionLabel, {
// title: `Verzija: ${data.version} <br> Avtor: ${data.version_author}`,
// customClass: 'dark-gray-tooltip',
// html: true,
// placement: 'bottom'
// })
// eslint-disable-next-line
const tooltip = new bootstrap.Tooltip(latestVersionLabel, {
title:
i18next.t('Verzija:') +
`${data.version} <br>` +
i18next.t('Avtor:') +
`${data.version_author}`,
customClass: 'dark-gray-tooltip',
html: true,
placement: 'bottom'
})
// Can't think of any better solution for the not disapearing label bug
const dateArea = document.querySelector('.date-scroller')
dateArea.addEventListener('click', () => tooltip.hide())
}
function removeOldMedia(images, audio, video) {
if (images !== null || audio !== null || video !== null) {
const media = [images, audio, video]
@@ -1998,7 +2201,7 @@ function showSelectedDateData(date) {
// classicOverview.classList.add('d-none')
// selectedOverview.classList.remove('d-none')
btnSaveIcon.firstChild.src = '/images/u_redo.svg'
btnSaveIcon.children[1].textContent = 'Obnovi'
btnSaveIcon.children[1].textContent = i18next.t('Obnovi')
btnSaveIcon.id = 'redo-action'
}
@@ -2038,7 +2241,7 @@ function changeCollapsedContent() {
function createHeadword() {
const { termInputField, headerwordTable } = window.dictionaryElements
if (!termInputField.value.length) alert('Vnesti morate termin')
if (!termInputField.value.length) alert(i18next.t('Vnesti morate termin'))
else {
const createHeadwordGroup = document.getElementById('create-headword-group')
const createdHeadwordGroup = document.getElementById(
@@ -2181,21 +2384,21 @@ function addField(form, element, content) {
if (formEditContent) {
switch (element) {
case newImageBtn:
spanName.textContent = 'SLIKA'
spanName.textContent = i18next.t('SLIKA')
inputField.name = 'image'
spanNameInfoTxt.textContent = 'Nova slika.'
spanNameInfoTxt.textContent = i18next.t('Nova slika.')
if (content) inputField.value = content
break
case newAudioBtn:
spanName.textContent = 'ZVOK'
spanName.textContent = i18next.t('ZVOK')
inputField.name = 'audio'
spanNameInfoTxt.textContent = 'Nov zvok.'
spanNameInfoTxt.textContent = i18next.t('Nov zvok.')
if (content) inputField.value = content
break
case newVideoBtn:
spanName.textContent = 'VIDEO'
spanName.textContent = i18next.t('VIDEO')
inputField.name = 'video'
spanNameInfoTxt.textContent = 'Nov video.'
spanNameInfoTxt.textContent = i18next.t('Nov video.')
if (content) inputField.value = content
break
}
@@ -2204,10 +2407,11 @@ function addField(form, element, content) {
element.parentElement.parentElement.parentElement
)
} else {
spanName.textContent = 'AVTOR'
spanName.textContent = i18next.t('AVTOR')
inputField.name = 'author'
spanNameInfoTxt.textContent =
'Dodajte ime in priimek naslednjega avtorja slovarja..'
spanNameInfoTxt.textContent = i18next.t(
'Dodajte ime in priimek naslednjega avtorja slovarja.'
)
form.insertBefore(
divMarginTop,
element.parentElement.parentElement.parentElement
@@ -2224,7 +2428,6 @@ function addConnectionField(form, element, data) {
const divRow = document.createElement('div')
const divColLg2 = document.createElement('div')
const divColLg4 = document.createElement('div')
const divColLg = document.createElement('div')
const colLg2Input = document.createElement('select')
const inputGroup = document.createElement('div')
const inputField = document.createElement('input')
@@ -2243,7 +2446,6 @@ function addConnectionField(form, element, data) {
divColLg2.appendChild(colLg2Input)
colLg2Input.appendChild(opt)
divRow.appendChild(divColLg4)
divRow.appendChild(divColLg)
divColLg4.appendChild(inputGroup)
inputGroup.appendChild(inputField)
inputGroup.appendChild(spanInputGroup)
@@ -2252,32 +2454,34 @@ function addConnectionField(form, element, data) {
divColSm.appendChild(spanNameInfoTxt)
divMarginTop.className = 'mt-4 added-field'
divSubjectName.className = 'subject-name'
divSubjectName.className =
'subject-name col-sm-6 d-flex justify-content-between'
spanName.className = 'input-name-txt'
divRow.className = 'row align-items-center'
divColLg2.className = 'col-lg-2 col-6'
divColLg4.className = 'col-lg-4 mt-2 mt-lg-0'
divColLg.className = 'col-lg align-items-center'
divColLg2.className = 'col-xl-2 col-4'
divColLg4.className = 'col-8 col-xl-6 col-xxl-4'
colLg2Input.className = 'name-input form-select d-inline'
colLg2Input.name = 'type'
inputGroup.className = 'input-group'
inputField.className = 'name-input d-inline form-control icon-trash mc-field'
inputField.className =
'name-input d-inline form-control icon-trash mc-field dispatch-tab'
spanInputGroup.className = 'input-group-text delete-author-btn'
spanInputGroup.id = 'trash-icon-btn'
spanInputGroup.addEventListener('click', deleteField)
imgTrashIcon.className = 'delete-author p-0'
imgTrashIcon.src = '/images/red-trash-icon.svg'
imgTrashIcon.alt = 'Delete'
divColSm.className = 'col-sm'
spanNameInfoTxt.className = 'name-info-txt mt-3'
spanName.textContent = 'POVEZAVA'
divColSm.className = 'col d-none d-xl-flex align-items-center'
spanNameInfoTxt.className = 'd-md-inline d-block name-info-txt mt-3 mt-sm-0'
spanNameInfoTxt.textContent = i18next.t('Nov povezan termin.')
spanName.textContent = i18next.t('POVEZANI TERMIN')
inputField.name = 'links'
opt.value = 'broader'
opt.text = 'Širši'
opt.text = i18next.t('Širši')
opt2.value = 'related'
opt3.value = 'narrow'
opt2.text = 'Sorodni'
opt3.text = 'Ožji'
opt2.text = i18next.t('Sorodni')
opt3.text = i18next.t('Ožji')
colLg2Input.add(opt2)
colLg2Input.add(opt)
colLg2Input.add(opt3)
@@ -2286,6 +2490,32 @@ function addConnectionField(form, element, data) {
divMarginTop,
element.parentElement.parentElement.parentElement
)
// Create mixed content buttons above input field
const mcDiv = document.createElement('div')
const supscriptBtn = document.createElement('button')
const subscriptBtn = document.createElement('button')
const supImg = document.createElement('img')
const subImg = document.createElement('img')
mcDiv.appendChild(supscriptBtn)
mcDiv.appendChild(subscriptBtn)
supscriptBtn.appendChild(supImg)
subscriptBtn.appendChild(subImg)
mcDiv.className = 'mc-buttons-group d-none'
supscriptBtn.className = 'mc-button mc-supscript'
supscriptBtn.type = 'button'
subscriptBtn.className = 'mc-button mc-subscript'
subscriptBtn.type = 'button'
supImg.src = '/images/superscript.svg'
supImg.className = 'mc-center-img'
subImg.className = 'mc-center-img'
subImg.src = '/images/subscript.svg'
divSubjectName.appendChild(mcDiv)
// eslint-disable-next-line
inputField.addEventListener('focus', () => showMCButtons(inputField, 'link'))
if (data) {
inputField.value = data.link
colLg2Input.value = data.type
@@ -2336,14 +2566,14 @@ function handleAreasClick({ target }) {
const saveButton = document.createElement('button')
saveButton.type = 'button'
cancelButton.type = 'button'
cancelButton.textContent = 'Prekliči'
cancelButton.textContent = i18next.t('Prekliči')
cancelButton.className = 'btn btn-secondary me-2'
cancelButton.style.height = '33px'
cancelButton.style.width = '105px'
cancelButton.addEventListener('click', () =>
abortEditing(newButtonGroup, tableButtons, tDataArea)
)
saveButton.textContent = 'POTRDI'
saveButton.textContent = i18next.t('POTRDI')
saveButton.type = 'button'
saveButton.className = 'btn btn-primary'
saveButton.style.height = '33px'
@@ -2666,7 +2896,7 @@ function checkLanguages() {
}
$('.summernote').summernote({
placeholder: 'Na kratko opišite zasnovo in namen slovarja.',
placeholder: i18next.t('Na kratko opišite zasnovo in namen slovarja.'),
height: 300,
minheight: 150,
toolbar: [
@@ -0,0 +1,24 @@
/* globals axios, i18next */
const exportForm = document.forms['dictionary-export']
exportForm.addEventListener('submit', async event => {
event.preventDefault()
const payload = Object.fromEntries(new FormData(event.target))
try {
await axios.post(event.target.action, payload)
// TODO This (page refresh) is a temporary hack. Replace with proper UI updating logic.
location.reload()
} catch (error) {
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
}
})
@@ -1,11 +1,16 @@
/* global axios, initPagination, removeAllChildNodes */
/* global axios, initPagination, removeAllChildNodes, i18next, dictionaryId */
{
const selectorEl = document.getElementById('select-extraction-name')
selectorEl.addEventListener('change', () => loadCandidates(selectorEl.value))
const resultsListEl = document.getElementById('page-results')
const importFormEl = document.getElementById('import-form')
const importButtonEl = document.getElementById('import-btn')
let termCandidates
let hitsPerPage
let numberOfAllPages
importFormEl.addEventListener('submit', submitForm)
async function loadCandidates(id) {
try {
const { data } = await axios.get(
@@ -18,6 +23,8 @@
const results = getDataForFirstPage(data)
renderResults(results)
updateDemoPager(1, numberOfAllPages)
importFormEl.action = `/api/v1/dictionaries/${dictionaryId}/import-extraction/${id}`
importButtonEl.disabled = false
} catch (error) {
console.log(error)
}
@@ -64,9 +71,27 @@
tdId.textContent = sequentialCount
tdName.textContent = candidate.kanonicnaoblika
tdSize.textContent = candidate.ranking
tdDate.textContent = candidate.pogostostpojavljanja
tdDate.textContent = candidate.pogostostpojavljanja[0]
rowEl.append(tdId, tdName, tdSize, tdDate)
resultsListEl.appendChild(rowEl)
})
}
async function submitForm(event) {
event.preventDefault()
const payload = Object.fromEntries(new FormData(event.target))
try {
await axios.post(event.target.action, payload)
alert(i18next.t('SLOVAR UVOŽEN'))
} catch (error) {
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
}
}
}
@@ -0,0 +1,7 @@
const nameEl = document.getElementById('name')
nameEl.addEventListener('input', enableButton)
function enableButton() {
const disabledBtn = document.getElementById('mpbtn')
disabledBtn.classList.remove('disabled')
}
@@ -1,16 +1,20 @@
/* global axios, removeAllChildNodes, bootstrap */
/* global axios, removeAllChildNodes, bootstrap, i18next */
const fileUploadContainerEl = document.getElementById('upload-files-container')
const fileUploadForm = document.forms['upload-files']
const fileInputEl = fileUploadForm.querySelector('input[type="file"]')
const filesListEl = document.getElementById('files-list')
const dropArea = document.querySelector('.drag-area')
const dragButton = dropArea.querySelector('button')
const dragInput = dropArea.querySelector('input')
const modalSpinner = new bootstrap.Modal(
document.getElementById('modal-spinner')
)
const modalAlert = new bootstrap.Modal(document.getElementById('alert-modal'))
let file
let fileListElCount = filesListEl.childElementCount
let isUploadInProgress = false
let isDeletionInProgress = false
const existingFileNames = [...filesListEl.children].map(
fileListEl => fileListEl.querySelector('.file-name').textContent
)
dragButton.onclick = () => {
dragInput.click()
@@ -68,96 +72,216 @@ fileInputEl.addEventListener('change', submitFiles)
filesListEl.addEventListener('click', handleFileClick)
async function submitFiles() {
// TODO Lock additional submits for the duration of this function execution?
if (isUploadInProgress) return
isUploadInProgress = true
fileUploadContainerEl.hidden = true
const MAX_FILE_SIZE = 10 ** 9 // 1 GB
const filesToUpload = []
const failedUploads = []
modalSpinner.toggle()
const succeededFileListEls = []
let didRemoveAnyFileListEls = false
for (const file of fileInputEl.files) {
const filename = file.name
const indexOfSameNamed = existingFileNames.indexOf(filename)
if (indexOfSameNamed !== -1) {
filesListEl.children[indexOfSameNamed].remove()
existingFileNames.splice(indexOfSameNamed, 1)
didRemoveAnyFileListEls = true
}
const fileListEl = createFileListEl(filename)
filesListEl.appendChild(fileListEl)
existingFileNames.push(filename)
if (file.size > MAX_FILE_SIZE) {
const failedUpload = {
filename: file.name,
filename,
message: 'File too large. Must not be over 1 GB.'
}
failedUploads.push(failedUpload)
updateFileListEl(fileListEl, { status: 'failed' })
continue
}
const payload = new FormData()
payload.set(fileInputEl.name, file)
filesToUpload.push([file, fileListEl])
}
if (didRemoveAnyFileListEls) reindexFileListEls()
for (const [file, fileListEl] of filesToUpload) {
try {
await axios.put(apiEndpointBase, payload)
const payload = new FormData()
payload.set(fileInputEl.name, file)
const { data: fileStats } = await axios.put(apiEndpointBase, payload, {
onUploadProgress: displayUploadProgress(fileListEl)
})
succeededFileListEls.push(fileListEl)
updateFileListEl(fileListEl, { status: 'success', fileStats })
} catch (error) {
const failedUpload = {
filename: file.name,
message: error.response.data
}
failedUploads.push(failedUpload)
updateFileListEl(fileListEl, { status: 'failed' })
}
}
try {
const { data: files } = await axios.get(apiEndpointBase)
updateFilesList(files)
} catch {
alert('Pri posodobljanju seznama naloženih datotek je prišlo do napake.')
}
fileInputEl.value = ''
displayFailedUploads(failedUploads)
modalSpinner.toggle()
succeededFileListEls.forEach(el => updateFileListEl(el, { status: 'done' }))
if (failedUploads.length) displayFailedUploads(failedUploads)
isUploadInProgress = false
fileUploadContainerEl.hidden = false
}
function updateFilesList(files) {
removeAllChildNodes(filesListEl)
files.forEach(({ filename, size, timeModified }, index) => {
const rowEl = document.createElement('tr')
const tdId = document.createElement('td')
const tdName = document.createElement('td')
const tdSize = document.createElement('td')
const tdDate = document.createElement('td')
const tdDelete = document.createElement('td')
tdId.textContent = index + 1
tdName.textContent = filename
tdName.className = 'filename'
tdSize.textContent = size
const formattedDate = new Date(timeModified).toLocaleDateString('sl-SL')
tdDate.textContent = formattedDate
const delBtn = document.createElement('button')
delBtn.className = 'p-0 delete-file delete-btn-table'
delBtn.type = 'button'
const deleteImg = document.createElement('img')
deleteImg.src = '/images/red-trash-icon.svg'
deleteImg.alt = 'Izbriši'
const delSpan = document.createElement('span')
delSpan.className = 'ms-2'
delSpan.textContent = 'Briši'
delBtn.appendChild(deleteImg)
delBtn.appendChild(delSpan)
tdDelete.appendChild(delBtn)
rowEl.append(tdId, tdName, tdSize, tdDate, tdDelete)
filesListEl.appendChild(rowEl)
})
function createFileListEl(filename) {
const indexEl = document.createElement('td')
indexEl.className = 'file-index'
indexEl.textContent = ++fileListElCount
const nameEl = document.createElement('td')
nameEl.className = 'file-name'
nameEl.textContent = filename
const sizeEl = document.createElement('td')
sizeEl.className = 'file-size'
const dateEl = document.createElement('td')
dateEl.className = 'file-date-modified'
const progressBarId = `progress-bar-${fileListElCount}`
const progressLabelEl = document.createElement('label')
progressLabelEl.className = 'me-1'
progressLabelEl.for = progressBarId
progressLabelEl.textContent = '0%'
const progressBarEl = document.createElement('progress')
progressBarEl.id = progressBarId
progressBarEl.className = 'upload-progress'
progressBarEl.value = 0
progressBarEl.max = 100
const lastEl = document.createElement('td')
lastEl.className = 'file-last-cell'
lastEl.append(progressLabelEl, progressBarEl)
const fileListEl = document.createElement('tr')
fileListEl.append(indexEl, nameEl, sizeEl, dateEl, lastEl)
return fileListEl
}
function updateFileListEl(fileListEl, { status, fileStats, index }) {
if (status === 'success') {
const nameEl = fileListEl.querySelector('.file-name')
nameEl.textContent = fileStats.filename
const sizeEl = fileListEl.querySelector('.file-size')
sizeEl.textContent = fileStats.size
const dateEl = fileListEl.querySelector('.file-date-modified')
const formattedDate = new Date(fileStats.timeModified).toLocaleDateString(
'sl-SL'
)
dateEl.textContent = formattedDate
const successImgEl = document.createElement('img')
successImgEl.src = '/images/valid.svg'
successImgEl.alt = i18next.t('Datoteka uspešno naložena')
const lastEl = fileListEl.querySelector('.file-last-cell')
removeAllChildNodes(lastEl)
lastEl.append(successImgEl)
} else if (status === 'done') {
const deleteImgEl = document.createElement('img')
deleteImgEl.src = '/images/red-trash-icon.svg'
deleteImgEl.alt = ''
const deleteSpanEl = document.createElement('span')
deleteSpanEl.className = 'ms-2'
deleteSpanEl.textContent = 'Briši'
const deleteButtonEl = document.createElement('button')
deleteButtonEl.className = 'p-0 delete-file delete-btn-table'
deleteButtonEl.append(deleteImgEl, deleteSpanEl)
const lastEl = fileListEl.querySelector('.file-last-cell')
removeAllChildNodes(lastEl)
lastEl.append(deleteButtonEl)
} else if (status === 'reindex') {
const indexEl = fileListEl.querySelector('.file-index')
indexEl.textContent = index + 1
} else if (status === 'failed') {
const failImgEl = document.createElement('img')
failImgEl.src = '/images/x_red.svg'
failImgEl.alt = i18next.t('Napaka pri nalaganju datoteke')
const lastEl = fileListEl.querySelector('.file-last-cell')
removeAllChildNodes(lastEl)
lastEl.append(failImgEl)
}
}
function displayFailedUploads(failedUploads) {
const modalContentEl = modalAlert._element.querySelector(
'.modal-alert-content'
)
modalContentEl.classList.remove('d-flex')
const descriptionEl = modalAlert._element.querySelector('#alert-text')
descriptionEl.textContent = i18next.t(
'Naslednje datoteke niso bile naložene zaradi navedenih razlogov:'
)
modalContentEl.querySelector('ul')?.remove()
const listEl = document.createElement('ul')
modalContentEl.append(listEl)
failedUploads.forEach(({ filename, message }) => {
const alertText = modalAlert.querySelector('#alert-text')
alertText.textContent = `NAPAKA - Ime datoteke: ${filename}, razlog: ${message}`
modalAlert.toggle()
const bulletEl = document.createElement('li')
bulletEl.textContent = `${filename} - ${message}`
listEl.appendChild(bulletEl)
})
modalAlert.toggle()
}
async function handleFileClick(e) {
if (e.target.closest('.delete-file')) {
if (isUploadInProgress) {
alert(
i18next.t('Brisanje je onemogočeno, doker se nalagajo nove datoteke.')
)
return
}
if (isDeletionInProgress) {
alert(i18next.t('Brisanje je onemogočeno, saj je eno še v procesu.'))
return
}
isDeletionInProgress = true
const fileEl = e.target.closest('tr')
const filename = fileEl.querySelector('.filename').textContent
const filename = fileEl.querySelector('.file-name').textContent
try {
await axios.delete(`${apiEndpointBase}/${filename}`)
fileEl.remove()
existingFileNames.splice(existingFileNames.indexOf(filename), 1)
reindexFileListEls()
isDeletionInProgress = false
} catch {
alert('Pri brisanju datoteke je prišlo do napake.')
alert(i18next.t('Pri brisanju datoteke je prišlo do napake.'))
}
}
}
function displayUploadProgress(fileListEl) {
const progressEl = fileListEl.querySelector('.upload-progress')
return function ({ loaded, total }) {
const percentCompleted = Math.round((loaded / total) * 100)
progressEl.setAttribute('value', percentCompleted)
progressEl.previousElementSibling.textContent = `${percentCompleted}%`
}
}
function reindexFileListEls() {
fileListElCount = filesListEl.childElementCount
for (let i = 0; i < fileListElCount; i++) {
const fileListEl = filesListEl.children[i]
updateFileListEl(fileListEl, { status: 'reindex', index: i })
}
}
@@ -16,15 +16,20 @@ async function onListClick({ target }) {
modalUseBtn.addEventListener('click', async () => {
await axios.delete(`/api/v1/extraction/${extractionId}`)
extractionEl.remove()
// TODO This (page refresh) is an unneeded workaround for an otherwise simple user friendlier solution.
location.reload()
})
} else if (target.classList.contains('btn-begin')) {
} else if (target.closest('.btn-begin')) {
const extractionEl = target.closest('.task')
const extractionId = extractionEl.dataset.id
await axios.put(`/api/v1/extraction/${extractionId}/begin`)
const responseModal = new bootstrap.Modal(
document.getElementById('begin-response')
)
const beginExtractionModalEl = document.getElementById('begin-response')
const responseModal = new bootstrap.Modal(beginExtractionModalEl)
responseModal.toggle()
// TODO This (page refresh) is a temporary hack. Replace with proper UI updating logic.
beginExtractionModalEl.addEventListener('hide.bs.modal', () =>
location.reload()
)
} else if (target.classList.contains('btn-duplicate')) {
const extractionEl = target.closest('.task')
const extractionId = extractionEl.dataset.id
@@ -1,4 +1,4 @@
/* global $, axios, bootstrap */
/* global $, axios, bootstrap, i18next */
$('.pick-multiple').select2()
$('.enter-multiple').select2({
@@ -41,8 +41,8 @@ async function handleSearch() {
}
function handleSearchError() {
const alertText = modalAlert.querySelector('#alert-text')
alertText.textContent = `NAPAKA pri iskanju`
const alertText = modalAlert._element.querySelector('#alert-text')
alertText.textContent = i18next.t('NAPAKA pri iskanju')
modalAlert.toggle()
}
@@ -32,7 +32,7 @@
tdId.textContent = sequentialCount
tdName.textContent = candidate.kanonicnaoblika
tdSize.textContent = candidate.ranking
tdDate.textContent = candidate.pogostostpojavljanja
tdDate.textContent = candidate.pogostostpojavljanja[0]
rowEl.append(tdId, tdName, tdSize, tdDate)
resultsListEl.appendChild(rowEl)
})
+6 -6
View File
@@ -1,4 +1,4 @@
/* global currentPagePath */
/* global currentPagePath, i18next */
// const currentPagePath = location.pathname
@@ -103,22 +103,22 @@ function initExtraction() {
btnStart.type = 'button'
btnImg.src = '/images/fi_arrow-right-circle.svg'
btnSpan.className = 'ms-1'
btnSpan.textContent = 'Začni'
btnSpan.textContent = i18next.t('Začni')
hr.className = 'mt-2 mb-3'
divSmFlex2.className = 'd-flex justify-content-between'
divSmFlexACMb.className = 'd-sm-flex align-items-center mb-0'
imgAlertCircle.src = '/images/alert-circle.svg'
spanNew.className = 'normal-gray ms-1'
spanNew.textContent = 'Nov'
spanNew.textContent = i18next.t('Nov')
divSmFlexACMbMe.className = 'd-sm-flex align-content-center mb-0 me-3'
divEditTask.className = 'align-items-center me-3 edit-task'
imgEditAlt.src = '/images/u_edit-alt.svg'
spanEdit.className = 'ms-1 normal-gray'
spanEdit.textContent = 'Uredi'
spanEdit.textContent = i18next.t('Uredi')
divDeleteTask.className = 'ms-3 align-items-center delete-task'
imgDeleteAlt.src = '/images/red-trash-icon.svg'
spanDelete.className = 'ms-1 normal-gray'
spanDelete.textContent = 'Briši'
spanDelete.textContent = i18next.t('Briši')
taskNewContainer.appendChild(divSmFlex)
divSmFlex.appendChild(divSmGrid)
@@ -233,7 +233,7 @@ function mobileMoveContent() {
primaryButton.style.whiteSpace = ''
}
navTitle.textContent = 'Urejanje'
navTitle.textContent = i18next.t('Urejanje')
siteHeading.style.display = 'block'
}
}
@@ -1,4 +1,4 @@
/* global axios, validator, removeJumpLogic */
/* global axios, validator, $, i18next */
/*
@@ -27,6 +27,7 @@ const listenRegisterBtn = event => {
loginHeader.className = loginHeader.className + ' d-none'
regDescription.className = regDescription.className.replace('d-none', '')
loginDescription.className = loginDescription.className + ' d-none'
clearErrorView()
}
const listenLoginBtn = event => {
@@ -38,6 +39,7 @@ const listenLoginBtn = event => {
regHeader.className = regHeader.className + ' d-none'
loginDescription.className = loginDescription.className.replace('d-none', '')
regDescription.className = regDescription.className + ' d-none'
clearErrorView()
}
regBtn.addEventListener('click', listenRegisterBtn)
@@ -106,6 +108,23 @@ function updateLoginRegisterErrorView(
}
}
function clearErrorView() {
Object.keys(registerErrorIndicatorpairs).forEach(key => {
registerErrorIndicatorpairs[key][0].style.visibility = 'hidden'
registerErrorIndicatorpairs[key][1].style.visibility = 'hidden'
})
document.querySelectorAll('.error-login-icon').forEach(e => {
e.style.visibility = 'hidden'
})
document.querySelector('.error-text').style.visibility = 'hidden'
document.getElementById('login-remember').checked = false
document.getElementById('terms-of-use').checked = false
document.getElementById('privacy-policy').checked = false
}
/*
Show error message from the label that represents the error returned from the server
Includes error X icons for login
@@ -152,14 +171,23 @@ function updateRegisterWindowOnSuccess(
footer.appendChild(document.createElement('button'))
const btn = footer.firstElementChild
btn.classList = 'btn btn-secondary text-secondary'
btn.textContent = 'ZAPRI'
btn.textContent = i18next.t('ZAPRI')
btn.ariaLabel = 'Close'
btn.dataset.bsDismiss = 'modal'
const successDescriptionPararaph = body.children[1]
successDescriptionPararaph.textContent = `Pozdravljeni ${name} ${surname},
na vaš elektronski naslov smo vam poslali sporočilo s povezavo, s katero boste potrdili svoj uporabniški račun na Terminološkem portalu.
Povezava za potrditev je veljavna ${days} dni.`
// successDescriptionPararaph.textContent = `Pozdravljeni ${name} ${surname},
// na vaš elektronski naslov smo vam poslali sporočilo s povezavo, s katero boste potrdili svoj uporabniški račun na Terminološkem portalu.
// Povezava za potrditev je veljavna ${days} dni.`
successDescriptionPararaph.textContent =
i18next.t('Pozdravljeni ') +
`${name} ${surname}, ` +
i18next.t(
'na vaš elektronski naslov smo vam poslali sporočilo s povezavo, s katero boste potrdili svoj uporabniški račun na Terminološkem portalu. Povezava za potrditev je veljavna '
) +
`${days} ` +
i18next.t('dni.')
}
// login and register
@@ -199,7 +227,7 @@ function updateRegisterWindowOnSuccess(
updateLoginRegisterErrorView(
registerErrorLabels[iterator],
true,
'Prazno obvezno polje'
i18next.t('Prazno obvezno polje')
)
failFrontendValidation = true
} else {
@@ -215,7 +243,7 @@ function updateRegisterWindowOnSuccess(
updateLoginRegisterErrorView(
'error-email',
true,
'Neveljavna e-pošta'
i18next.t('Neveljavna e-pošta')
)
} else {
updateLoginRegisterErrorView('error-email', false)
@@ -226,7 +254,7 @@ function updateRegisterWindowOnSuccess(
updateLoginRegisterErrorView(
'error-password',
true,
'Geslo je prekratko'
i18next.t('Geslo je prekratko')
)
} else {
updateLoginRegisterErrorView('error-password', false)
@@ -237,7 +265,7 @@ function updateRegisterWindowOnSuccess(
updateLoginRegisterErrorView(
'error-password-repeat',
true,
'Geslo se ne ujema'
i18next.t('Geslo se ne ujema')
)
}
}
@@ -263,11 +291,11 @@ function updateRegisterWindowOnSuccess(
// event.target.messageBind.textContent = data
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
showErrorReturnedFromServer(
@@ -279,3 +307,28 @@ function updateRegisterWindowOnSuccess(
}
}
}
function registerConditions() {
// Requirement 1: Terms of Use Checkbox checked
const requirement1 = document.getElementById('terms-of-use')
// Requirement 2: Privacy Policy checked
const requirement2 = document.getElementById('privacy-policy')
const registerButton = document.getElementById('regbtnmain')
if (requirement1.checked && requirement2.checked) {
registerButton.disabled = false
} else {
registerButton.disabled = true
}
}
document
.getElementById('terms-of-use')
.addEventListener('change', registerConditions)
document
.getElementById('privacy-policy')
.addEventListener('change', registerConditions)
$('#staticBackdrop').on('hidden.bs.modal', function () {
clearErrorView()
})
@@ -154,6 +154,21 @@ function searchQuery(searchString, searchFilterDOM = {}) {
document.location.href = url
}
function searchQueryWithExistingFilters(searchString) {
const stringBuilder = `/iskanje?q=${searchString}`
const thisUrl = new URL(location)
const url = new URL(stringBuilder, location.protocol + '//' + location.host)
thisUrl.searchParams.forEach((value, key, parent) => {
// console.log(`VALUE: ${value}`)
if (!(key === 'q' || key === 'p')) {
url.searchParams.append(key, value)
}
})
document.location.href = url
}
// end search implementation functions
// search filter functions
@@ -173,7 +188,11 @@ function sbmFn(sbm) {
inputString = '*'
}
searchQuery(inputString, searchFilterDOM)
if (sbm === document.querySelector('.search-btn-a')) {
searchQuery(inputString, searchFilterDOM)
} else {
searchQueryWithExistingFilters(inputString)
}
})
}
}
+57 -19
View File
@@ -1,21 +1,42 @@
const allMixedContentFields = document.querySelectorAll('.mc-field')
allMixedContentFields.forEach(el =>
el.addEventListener('focusin', () => showMCButtons(el))
el.addEventListener('focus', () => showMCButtons(el))
)
document.addEventListener('keypress', e => {
if (e.key === 'Enter' && e.target.classList.contains('dispatch-tab')) {
const form = event.target.form
const index = Array.prototype.indexOf.call(form, e.target)
form.elements[index + 1]?.focus()
e.preventDefault()
const currentNode = e.target
const allElements = document.querySelectorAll('input, select, textarea')
const currentIndex = [...allElements].findIndex(el =>
currentNode.isEqualNode(el)
)
const targetIndex = (currentIndex + 1) % allElements.length
allElements[targetIndex].focus()
}
})
function showMCButtons(element) {
const parent = element.parentElement.parentElement.parentElement
function showMCButtons(element, linkTerm) {
let parent
if (linkTerm) {
parent = element.parentElement.parentElement.parentElement.parentElement
} else {
parent = element.parentElement.parentElement.parentElement
}
const mainContent = document.getElementById('offset-main')
const sideMenu = document.querySelector('.content-nav-content')
const btnGrp = parent.querySelector('.mc-buttons-group')
// Warning, do not touch *_*
document.addEventListener('click', function (event) {
if (mainContent.contains(event.target) || sideMenu.contains(event.target)) {
if (element !== event.target && document.activeElement !== element) {
if (!parent.contains(event.target)) {
btnGrp.classList.add('d-none')
}
}
}
})
btnGrp.classList.remove('d-none')
const btnGrpChildren = btnGrp.children
const childrenBtns = Array.from(btnGrpChildren)
@@ -29,10 +50,10 @@ function showMCButtons(element) {
{ once: true }
)
)
document.addEventListener('click', function (event) {
if (parent !== event.target && !parent.contains(event.target)) {
btnGrp.classList.add('d-none')
}
document.addEventListener('keyup', function (e) {
const selectedEl = document.activeElement
if (!parent.contains(selectedEl)) btnGrp.classList.add('d-none')
})
}
@@ -50,8 +71,9 @@ function addMixedContentInput(el, selectedEl) {
inputText.substring(0, selectedStart) +
'<b>' +
inputText.substring(selectedStart, selectedEnd) +
'</b> ' +
'</b>' +
inputText.substring(selectedEnd)
placeCaret(selectedEl, selectedEnd + 7)
}
if (el.classList.contains('mc-italic') && selectedText.length) {
@@ -59,8 +81,9 @@ function addMixedContentInput(el, selectedEl) {
inputText.substring(0, selectedStart) +
'<i>' +
inputText.substring(selectedStart, selectedEnd) +
'</i> ' +
'</i>' +
inputText.substring(selectedEnd)
placeCaret(selectedEl, selectedEnd + 7)
}
if (el.classList.contains('mc-supscript') && selectedText.length) {
@@ -68,8 +91,9 @@ function addMixedContentInput(el, selectedEl) {
inputText.substring(0, selectedStart) +
'<sup>' +
inputText.substring(selectedStart, selectedEnd) +
'</sup> ' +
'</sup>' +
inputText.substring(selectedEnd)
placeCaret(selectedEl, selectedEnd + 11)
}
if (el.classList.contains('mc-subscript') && selectedText.length) {
@@ -77,27 +101,41 @@ function addMixedContentInput(el, selectedEl) {
inputText.substring(0, selectedStart) +
'<sub>' +
inputText.substring(selectedStart, selectedEnd) +
'</sub> ' +
'</sub>' +
inputText.substring(selectedEnd)
placeCaret(selectedEl, selectedEnd + 11)
}
if (el.classList.contains('mc-hyperlink') && selectedText.length) {
selectedEl.value =
inputText.substring(0, selectedStart) +
'<link url="">' +
'<a href="">' +
inputText.substring(selectedStart, selectedEnd) +
'</link> ' +
'</a>' +
inputText.substring(selectedEnd)
}
if (el.classList.contains('mc-line-break')) {
selectedEl.value =
inputText.substring(0, selectedStart) +
'<br />' +
'<br/>' +
inputText.substring(selectedEnd)
placeCaret(selectedEl, selectedEnd + 5)
el.removeEventListener('click', () => addMixedContentInput, false)
}
}
// selectedEl.focus()
// selectedEl.setSelectionRange(selectedStart, selectedEnd)
function placeCaret(elem, caretPos) {
if (elem != null) {
if (elem.createTextRange) {
const range = elem.createTextRange()
range.move('character', caretPos)
range.select()
} else {
if (elem.selectionStart) {
elem.focus()
elem.setSelectionRange(caretPos, caretPos)
} else elem.focus()
}
}
}
@@ -27,6 +27,8 @@
return await axios.get(url)
} */
// TODO MARK FOR REVIEW WHETHER THIS METHODS ARE STILL NEEDED
function prepareQueryArrayForArrayWithIDs(page, searchQuery, filters = {}) {
const qParams = new URL(location).searchParams
qParams.set('p', page)
@@ -0,0 +1,11 @@
/* global isI18nReady */
isI18nReady.then(t => {
const alertText = document.querySelector('#alert-text')
alertText.textContent = t(
'Ali želite zbrisati ta profil. S tem bodo izbrisani vsi podatki, ki ste jih ustvarili'
)
})
const redConfirm = document.querySelector('#modal-use-btn')
redConfirm.style.backgroundColor = '#AC7171'
@@ -0,0 +1,26 @@
// Note to myself: please optimize and remove the redundacy of the code written in multiple classes to achieve the same result as this
const focusOnCompletePromtBase = queryInput => {
queryInput.focus()
queryInput.select()
}
// Tradeoff: Declare a variable for the element to reduce duplication?
const inputQuery = document.querySelector('#search-query')
if (inputQuery) {
focusOnCompletePromtBase(inputQuery)
if (window.location.pathname === '/slovarji') {
document
.querySelector('#dicts-search-btn')
.addEventListener('click', () => {
focusOnCompletePromtBase(inputQuery)
})
document
.querySelector('#search-in-filter-modal')
.addEventListener('click', () => {
focusOnCompletePromtBase(inputQuery)
})
}
}
@@ -0,0 +1,59 @@
/* global $, axios, i18next */
// Function to verify password and repeat password
function verifyPassword() {
const password = document.getElementById('reset-password').value
const repeatPassword = document.getElementById('reset-password-repeat').value
if (password !== repeatPassword) {
alert(i18next.t('Gesli se ne ujemata')) // 'Passwords do not match')
return false
}
return true
}
// Handle submit event
document
.querySelector('#reset-and-redirect')
.addEventListener('submit', event => {
event.preventDefault()
if (verifyPassword()) {
const password = document.getElementById('reset-password').value
const repeatPassword = document.getElementById(
'reset-password-repeat'
).value
const token = document.getElementById('token').value
// const email = document.getElementById('email').value
// const data = { password, repeatPassword, token, email }
axios
.post('/api/v1/users/reset-passwordPLACEHOLDER_URL', {
password,
repeatPassword,
token
})
.then(response => {
if (response.data.success) {
$('#reset-pass-info').modal('show')
// window.location = '/'
} else {
alert(response.data.message)
}
})
.catch(error => {
// Very unlikely, but can happen
alert(i18next.t('Napaka na strežniku'))
console.log(error)
// DEBUG SUCCESS DUE TO NO ENDPOINT $('#reset-pass-info').modal('show') <<- REMOVE
})
}
})
// Handle cancel event
document.querySelector('#cancel-btn').addEventListener('click', event => {
event.preventDefault()
window.location = '/'
})
// Handle redirect on success
document.querySelector('#modal-fp-info-close').addEventListener('click', () => {
window.location = '/'
})
+203 -45
View File
@@ -1,4 +1,14 @@
/* global $, bootstrap */
/* global $, bootstrap, axios, i18next, i18nextHttpBackend */
// eslint-disable-next-line no-unused-vars
const isI18nReady = i18next.use(i18nextHttpBackend).init({
lng: document.documentElement.lang ?? 'sl',
ns: 'core',
nsSeparator: false,
keySeparator: false,
...(window.inDevEnv && { saveMissing: true }),
...(!window.inDevEnv && { fallbackLng: false })
})
const windows = ['#suggestions-root', '.advanced-search-root', '.kbd-root']
@@ -302,7 +312,7 @@ function renderSuggestions(
ajustElementSettings(preElement, options)
preElement.textContent = 'Za to besedo še ni podatkov.'
preElement.textContent = i18next.t('Za to besedo še ni podatkov.')
preElement.disabled = true
preElement.classList = ['w-100']
preElement.classList += ` ${type}-sugg`
@@ -646,31 +656,53 @@ document.querySelectorAll('.loginregisterlabel').forEach(label => {
/**
* Enables pagination logic for the specified pager UI.
*
* @param {string} paginationRootElId - Pager element id.
* @param {(string|string[])} paginationRootElIds - Pager element id.
* @param {function} onPageChange - Gets called with the number of the page the user requested.
* @returns {function} - Call it with (newCurrentPage, newNumOfAllPages) to update the ui. Or without arguments, after handling a potential error.
*/
function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
const rootEl = document.getElementById(paginationRootElId)
const btnFirstPage = rootEl.querySelector('.first-page')
const btnPreviousPage = rootEl.querySelector('.previous-page')
const btnNextPage = rootEl.querySelector('.next-page')
const btnLastPage = rootEl.querySelector('.last-page')
const formEl = rootEl.querySelector('form')
const pageInputEl = formEl.querySelector('input')
const pagesCountDisplayEl = formEl.querySelector('.pages-total')
function initPagination(paginationRootElIds, onPageChange, currentPage = 1) {
let reqLock = false
let numOfAllPages
const backwardBtnEls = []
const forwardBtnEls = []
const pageInputEls = []
const pagesCountDisplayEls = []
rootEl.addEventListener('click', handleButtonClick)
formEl.addEventListener('submit', handleFormSubmit)
if (Array.isArray(paginationRootElIds)) {
paginationRootElIds.forEach(id => initControls(id))
} else {
initControls(paginationRootElIds)
}
const allControlEls = [...backwardBtnEls, ...forwardBtnEls, ...pageInputEls]
function handleButtonClick({ target }) {
function initControls(paginationRootElId) {
const rootEl = document.getElementById(paginationRootElId)
const btnFirstPage = rootEl.querySelector('.first-page')
const btnPreviousPage = rootEl.querySelector('.previous-page')
const btnNextPage = rootEl.querySelector('.next-page')
const btnLastPage = rootEl.querySelector('.last-page')
const formEl = rootEl.querySelector('form')
const pageInputEl = formEl.querySelector('input')
const pagesCountDisplayEl = formEl.querySelector('.pages-total')
numOfAllPages = +pagesCountDisplayEl.textContent
backwardBtnEls.push(btnFirstPage, btnPreviousPage)
forwardBtnEls.push(btnNextPage, btnLastPage)
pageInputEls.push(pageInputEl)
pagesCountDisplayEls.push(pagesCountDisplayEl)
rootEl.addEventListener('click', e => {
handleButtonClick(e, paginationRootElId)
})
formEl.addEventListener('submit', e => handleFormSubmit(e, pageInputEl))
}
function handleButtonClick({ target }, paginationRootElId) {
if (reqLock) return
const buttonEl = target.closest(`#${paginationRootElId} button`)
if (!buttonEl) return
const numOfAllPages = +pagesCountDisplayEl.textContent
if (buttonEl.classList.contains('first-page')) {
if (currentPage === 1) return
@@ -691,13 +723,13 @@ function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
}
}
function handleFormSubmit(e) {
function handleFormSubmit(e, pageInputEl) {
e.preventDefault()
if (reqLock) return
const inputValue = +pageInputEl.value
if (!(inputValue > 0 && inputValue <= pagesCountDisplayEl.textContent)) {
alert('Nepravilna vrednost strani')
if (!(inputValue > 0 && inputValue <= numOfAllPages)) {
alert(i18next.t('Nepravilna vrednost strani'))
pageInputEl.value = currentPage
return
}
@@ -708,20 +740,12 @@ function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
function enableLock() {
reqLock = true
btnFirstPage.disabled = true
btnPreviousPage.disabled = true
btnNextPage.disabled = true
btnLastPage.disabled = true
pageInputEl.disabled = true
allControlEls.forEach(el => (el.disabled = true))
}
function disableLock() {
reqLock = false
btnFirstPage.disabled = false
btnPreviousPage.disabled = false
btnNextPage.disabled = false
btnLastPage.disabled = false
pageInputEl.disabled = false
allControlEls.forEach(el => (el.disabled = false))
}
function updatePagerUi(newCurrentPage, newNumOfAllPages) {
@@ -729,23 +753,20 @@ function initPagination(paginationRootElId, onPageChange, currentPage = 1) {
if (!newCurrentPage) return
currentPage = newCurrentPage
pageInputEl.value = newCurrentPage
pagesCountDisplayEl.textContent = newNumOfAllPages
numOfAllPages = newNumOfAllPages
pageInputEls.forEach(el => (el.value = newCurrentPage))
pagesCountDisplayEls.forEach(el => (el.textContent = newNumOfAllPages))
if (newCurrentPage === 1) {
btnFirstPage.disabled = true
btnPreviousPage.disabled = true
backwardBtnEls.forEach(el => (el.disabled = true))
} else {
btnFirstPage.disabled = false
btnPreviousPage.disabled = false
backwardBtnEls.forEach(el => (el.disabled = false))
}
if (newCurrentPage === newNumOfAllPages) {
btnNextPage.disabled = true
btnLastPage.disabled = true
forwardBtnEls.forEach(el => (el.disabled = true))
} else {
btnNextPage.disabled = false
btnLastPage.disabled = false
forwardBtnEls.forEach(el => (el.disabled = false))
}
}
@@ -923,11 +944,11 @@ if (registerSwithcButton) {
function initSelect2(querySelector, placeholder) {
$(querySelector).select2({
allowClear: true,
// allowClear: true,
placeholder: placeholder
})
$(querySelector).val(null).trigger('change')
// $(querySelector).val(null).trigger('change')
}
$(document).ready(function () {
@@ -935,7 +956,7 @@ if (registerSwithcButton) {
$('.select-search-field').select2({})
initSelect2('.select-domain-field', 'Področje')
initSelect2('.select-src-lang-field', 'Izvorni jezik')
initSelect2('.select-src-lang-field', 'Jezik iskanja')
initSelect2('.select-dest-lang-field', 'Ciljni jezik')
initSelect2('.select-dict-field', 'Slovar')
initSelect2('.select-source-field', 'Vir')
@@ -978,7 +999,7 @@ if (registerSwithcButton) {
$('.select-search-field').select2({})
initSelect2('.select-domain-field', 'Področje')
initSelect2('.select-src-lang-field', 'Izvorni jezik')
initSelect2('.select-src-lang-field', 'Jezik iskanja')
initSelect2('.select-dest-lang-field', 'Ciljni jezik')
initSelect2('.select-dict-field', 'Slovar')
initSelect2('.select-source-field', 'Vir')
@@ -1097,7 +1118,7 @@ function transferText(sideMenuText, removeOptionalBreak = false) {
const optionalBreak = document.getElementById('disposable-break')
if (document.body.clientWidth <= 1200) {
if (window.innerWidth < 1200) {
navTitle.textContent = siteHeadingTextContent
siteHeading.style.display = 'none'
if (removeOptionalBreak) {
@@ -1111,3 +1132,140 @@ function transferText(sideMenuText, removeOptionalBreak = false) {
}
}
}
function replaceContainer(id, HTMLContent) {
const el = document.getElementById(id)
if (el) {
el.innerHTML = HTMLContent
}
}
// STATE MANAGER FOR WINDOWS IN FORGOT PASSWORD
class StateManager {
constructor() {
this.state = {}
}
setState(newState) {
this.state = { ...this.state, ...newState }
}
getState() {
return this.state
}
}
class StateManagerInvoker {
constructor(stateManager, invokeFunction) {
this.stateManager = stateManager
this.invokeFn = invokeFunction
}
setState(newState) {
this.stateManager.setState(newState)
this.invoke()
}
invoke() {
this.invokeFn()
}
}
const stateManager = new StateManager()
const forgottenPasswordInvoker = new StateManagerInvoker(stateManager, () => {
function closeAllFPRelatedModals() {
$('#staticBackdrop').modal('hide')
$('#reset-pass-modal').modal('hide')
$('#reset-pass-info').modal('hide')
}
function showLoginModal() {
$('#staticBackdrop').modal('show')
}
function showResetPasswordModal() {
$('#reset-pass-modal').modal('show')
}
function showResetPasswordModalSuccessOrFail() {
$('#reset-pass-info').modal('show')
}
function apllyDescriptionAccordingToState() {
$('#alert-text').text(stateManager.getState().fpassWindowDescription)
}
closeAllFPRelatedModals()
switch (stateManager.getState().fpassWindowState) {
case ForgotPasswordState.LOGIN_SIGNUP:
showLoginModal()
break
case ForgotPasswordState.FORGOT_PASSWORD_MODAL:
showResetPasswordModal()
break
case ForgotPasswordState.FORGOT_PASSWORD_ERROR:
case ForgotPasswordState.FORGOT_PASSWORD_SUCCESS:
showResetPasswordModalSuccessOrFail()
apllyDescriptionAccordingToState()
break
default:
console.log('Unknown state')
}
})
const ForgotPasswordState = {
LOGIN_SIGNUP: 1,
FORGOT_PASSWORD_MODAL: 2,
FORGOT_PASSWORD_ERROR: 3,
FORGOT_PASSWORD_SUCCESS: 4
}
function onForgotPassword() {
forgottenPasswordInvoker.setState({
fpassWindowState: ForgotPasswordState.FORGOT_PASSWORD_MODAL
})
}
function onCancelForgotPassword() {
forgottenPasswordInvoker.setState({
fpassWindowState: ForgotPasswordState.LOGIN_SIGNUP
})
}
function onSendForgottenEmailRequest() {
axios
.post('/REPLACETHISDUMMYURL', {
usernameOrEmail: document.getElementById('forgot-pass-input').value
})
.then(res => {
// const EMAIL = 'DUMMY_EMAIL'
// State manager because we don't want to invoker twice
// it is required to update description first before updating state of the invoker
stateManager.setState({
fpassWindowDescription: i18next.t(
'Na vaš elektronski naslov smo vam posredovali povezavo za ponastavitev gesla. Prosimo preverite svoj elektronski predal.'
)
})
forgottenPasswordInvoker.setState({
fpassWindowState: ForgotPasswordState.FORGOT_PASSWORD_SUCCESS
})
})
.catch(err => {
stateManager.setState({
fpassWindowDescription: i18next.t(
'Prišlo je do napake pri pošiljanju sporočila na vaš elektronski naslov. Poskusite ponovno.'
)
})
forgottenPasswordInvoker.setState({
fpassWindowState: ForgotPasswordState.FORGOT_PASSWORD_ERROR
})
console.log(err)
})
}
$('#modal-fp-cancel-btn').on('click', onCancelForgotPassword)
$('#modal-fp-use-btn').on('click', onSendForgottenEmailRequest)
$('#modal-fp-info-close').on('click', () => $('#reset-pass-info').modal('hide'))
$('#forgotten-password').on('click', onForgotPassword)
@@ -1,4 +1,5 @@
/* global $, axios, initPagination, removeAllChildNodes, closeUtilityContainers, prepareQueryArrayForArrayWithIDs, getDataFromURLSearchParams, prepareQueryParams, focusOnCompletePrompt */
/* global $, axios, initPagination, removeAllChildNodes, closeUtilityContainers, prepareQueryArrayForArrayWithIDs,
getDataFromURLSearchParams, prepareQueryParams, focusOnCompletePrompt, i18next */
{
/*
@@ -117,11 +118,11 @@
return page
} catch (error) {
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
+45 -301
View File
@@ -1,10 +1,15 @@
/* global $, axios, currentPagePath, initPagination, removeAllChildNodes, transferText, tooltipTriggerList, tooltipList, reinitalizeDefaultTooltipSet, createTooltip */
/* global $, axios, currentPagePath, initPagination,
removeAllChildNodes, transferText, tooltipTriggerList,
tooltipList, createTooltip, resetTooltipTriggerList,
transferTextExtended, i18next */
// position correction functions
function adjustOffsetBy() {
// const { offsetMain, fixedTopSection } = window.dictionaryElements
const BROWSER_UNUSUAL_OFFSET = 17 // computer from chrome
const offsetMain = document.querySelector('#offset-main')
const fixedTopSection = document.querySelector('#fixed-top-section')
@@ -14,7 +19,7 @@ function adjustOffsetBy() {
// const adminNavMobile = document.getElementsByClassName('admin-nav')
const headerPadding = document.getElementById('header-padding')
if (document.body.clientWidth < 1200) {
if (document.body.clientWidth + BROWSER_UNUSUAL_OFFSET < 1200) {
if (offsetHeaderPadding !== null) offsetMain.style.paddingTop = `0px`
} else {
for (let i = 0; i < offsetHeader.length; i++) {
@@ -80,8 +85,14 @@ function mobileMoveContent() {
'.header-container-divider-right'
)
// let actualInnerWidth = $("body").prop("clientWidth"); // El. width minus scrollbar width
// let actualInnerWidth = $("body").prop("scrollWidth"); // El. width minus scrollbar width
// const BROWSER_UNUSUAL_OFFSET = 17 // computer from chrome
// console.log($('body').innerWidth() + BROWSER_UNUSUAL_OFFSET)
try {
if (document.body.clientWidth <= 1200) {
if (window.innerWidth < 1200) {
if (secondaryButton) {
mobileRightHolder.appendChild(secondaryButton)
// secondaryButton.style.height = '28px'
@@ -98,9 +109,11 @@ function mobileMoveContent() {
primaryButton.style.whiteSpace = 'nowrap'
}
navTitle.textContent = siteHeadingTextContent
siteHeading.style.display = 'none'
// siteHeading.style.display = 'none'
siteHeading.style.display = 'inline' // I know this is hacky, but sadly due to design this is mandatory in order to fix the bug
}
if (document.body.clientWidth > 1200) {
if (window.innerWidth >= 1200) {
if (secondaryButton) {
headerContainerRight.appendChild(secondaryButton)
secondaryButton.style.height = ''
@@ -117,7 +130,7 @@ function mobileMoveContent() {
primaryButton.style.whiteSpace = ''
}
navTitle.textContent = 'Urejanje'
navTitle.textContent = i18next.t('Urejanje')
siteHeading.style.display = 'block'
}
} catch (e) {}
@@ -128,7 +141,11 @@ if (resultsListEl) {
resultsListEl.addEventListener('click', onResultClick)
}
const initialPage = +new URL(location).searchParams.get('p') || 1
const updatePager = initPagination('pagination', onPageChange, initialPage)
const updatePager = initPagination(
['pagination-top', 'pagination-bottom'],
onPageChange,
initialPage
)
async function onPageChange(newPage) {
const receivedPageNumber = await changePage(newPage)
@@ -146,7 +163,16 @@ async function changePage(newPage) {
removeAllChildNodes(resultsListEl)
renderResults(resultsMarkup)
updatePager(page, numberOfAllPages)
reinitalizeDefaultTooltipSet()
// reinitalizeDefaultTooltipSet()
// console.log($('[data-toggle="tooltip"]'))
// $('[data-toggle="tooltip"]').tooltip()
// toltip reinitialization after moving a page
resetTooltipTriggerList()
if (tooltipTriggerList.length > 0) {
// initialize tooltips
tooltipList(null, 'dark-gray-tooltip') // ADD for tooltip debug in the end -> [0].show()
}
/*
try {
@@ -160,12 +186,12 @@ async function changePage(newPage) {
return page
} catch (error) {
// console.log(error)
let message = 'Prišlo je do napake.'
let message = i18next.t('Prišlo je do napake.')
if (error.response?.data) {
message = error.response.data
} else if (error.request) {
return // return to bypass error caused (assumed) by popstate on iOS/MacOS
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
message = i18next.t('Strežnik ni dosegljiv. Poskusite kasneje.')
}
alert(message)
updatePager()
@@ -210,119 +236,10 @@ function onResultClick(e) {
try {
if (tooltipTriggerList.length > 0) {
// initialize tooltips
tooltipList(null, 'gray-tooltip') // ADD for tooltip debug in the end -> [0].show()
tooltipList(null, 'dark-gray-tooltip') // ADD for tooltip debug in the end -> [0].show()
}
} catch (e) {}
/*
// refresh: bool
function largeStringsOnSmallScreen(alwaysRefresh) {
let headwordTexts
let translationWords
let synonymWords
function init() {
headwordTexts = [...$('.rihw')]
translationWords = [...$('.term-h')].map(e => {
return e.children[0]
})
synonymWords = [...$('.syn-h'), ...$('.risy')]
}
function setupToolTips() {
setDynamicTooltipList([])
if (headwordTexts) {
headwordTexts.map(ttElement =>
createTooltip(ttElement, ttElement.innerHTML, '')
)
// setDynamicTooltipList([...dynamicTooltipList, ...tt])
}
if (translationWords) {
translationWords.map(ttElement =>
createTooltip(ttElement, ttElement.innerHTML, '')
)
// setDynamicTooltipList([...dynamicTooltipList, ...tt])
}
if (synonymWords) {
synonymWords.map(ttElement =>
createTooltip(ttElement, ttElement.innerHTML, '')
)
// setDynamicTooltipList([...dynamicTooltipList, ...tt])
}
// console.log(dynamicTooltipList)
}
if (!headwordTexts || !translationWords || !synonymWords || alwaysRefresh) {
init()
}
function initTooltips() {
try {
// if (dynamicTooltipList.length || alwaysRefresh) {
setupToolTips()
// }
} catch (e) {}
}
function removeTooltips() {
try {
$('.rihw').tooltip('dispose')
$('.term-h').children().tooltip('dispose')
$('.syn-h').tooltip('dispose')
$('.risy').tooltip('dispose')
} catch (e) {}
}
function manageResize() {
const tmpTerms = [...$('.term-h')].map(e => {
return e.children[0]
})
const elements = [...tmpTerms, ...$('.syn-h')]
// console.log(document.documentElement.clientWidth)
const dcw = document.documentElement.clientWidth
const checkBorders = (dcw > 991 && dcw < 1600) || dcw < 370
if (checkBorders) {
const TEXT_LIMIT = 17
elements.forEach(el => {
el.dataset.textStore = el.innerHTML.includes('...')
? el.dataset.textStore
: el.innerHTML
el.innerHTML = `${el.innerHTML.slice(0, TEXT_LIMIT)}${
el.innerHTML.length > TEXT_LIMIT ? '...' : ''
}`
})
initTooltips()
} else {
elements.forEach(el => {
if (el.dataset.textStore) {
el.innerHTML = el.dataset.textStore
}
})
removeTooltips()
}
}
return {
init: function () {
init()
},
refresh: function () {
init()
try {
setupToolTips()
} catch (e) {}
},
manageResize: manageResize
}
}
const textsScreenManager = largeStringsOnSmallScreen(true)
textsScreenManager.manageResize()
window.onresize = textsScreenManager.manageResize
*/
// refresh: bool
function largeStringsOnSmallScreen(alwaysRefresh) {
let headwordTexts
@@ -336,30 +253,6 @@ function largeStringsOnSmallScreen(alwaysRefresh) {
synonymWords = [...$('.syn-h'), ...$('.risy')]
}
/*
function setupToolTips() {
setDynamicTooltipList([])
if (headwordTexts) {
headwordTexts.map(ttElement =>
createTooltip(ttElement, ttElement.innerHTML, '')
)
// setDynamicTooltipList([...dynamicTooltipList, ...tt])
}
if (translationWords) {
translationWords.map(ttElement =>
createTooltip(ttElement, ttElement.innerHTML, '')
)
// setDynamicTooltipList([...dynamicTooltipList, ...tt])
}
if (synonymWords) {
synonymWords.map(ttElement =>
createTooltip(ttElement, ttElement.innerHTML, '')
)
// setDynamicTooltipList([...dynamicTooltipList, ...tt])
}
// console.log(dynamicTooltipList)
} */
if (!headwordTexts || !translationWords || !synonymWords || alwaysRefresh) {
init()
}
@@ -379,169 +272,20 @@ function largeStringsOnSmallScreen(alwaysRefresh) {
ttElement.tooltip('dispose')
} catch (e) {}
}
/*
function initTooltips() {
try {
// if (dynamicTooltipList.length || alwaysRefresh) {
setupToolTips()
// }
} catch (e) {}
}
function removeTooltips() {
try {
$('.rihw').tooltip('dispose')
$('.term-h').children().tooltip('dispose')
$('.syn-h').tooltip('dispose')
$('.risy').tooltip('dispose')
} catch (e) {}
}
*/
/* let OLD_TEXT_LIMIT = 5000 // Guard to not prevent overdisposing
function manageResize() {
const tmpTerms = [...$('.term-h')].map(e => {
return e.children[0]
})
const elements = [...tmpTerms, ...$('.syn-h')]
// console.log(document.documentElement.clientWidth) */
/*
$('.word-constraint').each((i, element) => {
// WRONG const wordBr = $(`.word-constraint:nth-child(${i}) > .word-breakable`)
const wordList = $(element).find('.word-breakable')
wordList.each((i, wordElement) => {
// console.log(wordElement.innerText)
if (
wordElement.clientWidth > element.clientWidth &&
wordElement.innerText.split(' ').length <= 1
) {
console.log('Lion')
createTooltip($(wordElement))
wordElement.classList.push('text-ellipsis')
} else {
removeTooltip($(wordElement))
// console.log(wordElement.classList)
wordElement.className = Array.from(wordElement.classList)
.filter(e => e !== 'text-ellipsis')
.join(' ')
// console.log(wordElement.classList)
}
})
// console.log(wordBr)
})
*/
/* const dcw = document.documentElement.clientWidth
// const checkBorders = (dcw > 420 && dcw < 750) || dcw < 370
let borderIndex
// check _common.scc long-text-strip and make sure the widths are aligned
if (dcw < 420) {
borderIndex = 0 // width = 8 chars (<420)
} else if (dcw < 750 || (dcw > 990 && dcw < 1750)) {
borderIndex = 1 // width = 12 chars (420 - 750, 990-1750)
} else if (dcw > 1750) {
borderIndex = 3 // width = 100% (>1759)
} else {
borderIndex = 2 // width = 25 chars (750-990)
}
let TEXT_LIMIT
if (borderIndex === 0) {
TEXT_LIMIT = 8
} else if (borderIndex === 1) {
TEXT_LIMIT = 12
} else if (borderIndex === 2) {
TEXT_LIMIT = 25
} else {
TEXT_LIMIT = null
}
if (OLD_TEXT_LIMIT !== TEXT_LIMIT) {
elements.forEach(el => {
// console.log(el.innerHTML)
if (TEXT_LIMIT && el.innerHTML.length > TEXT_LIMIT) {
console.log(`DEBUG TEXT LIMIT: ${TEXT_LIMIT}`)
console.log(`DEBUG EL LEN: ${el.innerHTML.length}`)
console.log(`DEBUG EL TEXT: ${el.innerHTML}`)
console.log('TOOLTIP CREATED')
createTooltipEl(el, 'gray-tooltip')
} else {
removeTooltip($(el))
}
})
}
OLD_TEXT_LIMIT = TEXT_LIMIT */
/*
if (checkBorders) {
console.log('HEYOO')
const TEXT_LIMIT = 17
elements.forEach(el => {
el.dataset.textStore = el.innerHTML.includes('...')
? el.dataset.textStore
: el.innerHTML
el.innerHTML = `${el.innerHTML.slice(0, TEXT_LIMIT)}${
el.innerHTML.length > TEXT_LIMIT ? '...' : ''
}`
})
initTooltips()
} else {
elements.forEach(el => {
if (el.dataset.textStore) {
el.innerHTML = el.dataset.textStore
}
})
removeTooltips()
}
*/
/* }
return {
init: function () {
init()
},
refresh: function () {
init()
},
manageResize: manageResize
} */
}
// const textsScreenManager = largeStringsOnSmallScreen(true)
// textsScreenManager.manageResize()
// window.onresize = textsScreenManager.manageResize
/*
function transferText(sideMenuText) {
const siteHeading = document.getElementById('site-heading')
const siteHeadingTextContent = siteHeading.textContent
const navTitle = document.getElementById('nav-title')
if (document.body.clientWidth <= 1200) {
navTitle.textContent = siteHeadingTextContent
siteHeading.style.display = 'none'
} else {
navTitle.textContent = sideMenuText
}
}
*/
window.addEventListener('load', () => {
$('[data-toggle="tooltip"]').tooltip()
})
function handleProperTextDisplay() {
// const BROWSER_UNUSUAL_OFFSET = 17
if (/\/iskanje/.test(currentPagePath)) {
transferText('Iskanje po slovarjih', true)
transferText('Iskanje po slovarjih', true, 'site-heading') //,
// BROWSER_UNUSUAL_OFFSET
// )
} else if (/\/termin/.test(currentPagePath)) {
transferText('', true)
transferText('', true, 'site-heading') // , BROWSER_UNUSUAL_OFFSET)
}
}
+6 -6
View File
@@ -1,4 +1,4 @@
/* global $, currentPagePath */
/* global $, currentPagePath, i18next */
// const currentPagePath = location.pathname
@@ -60,13 +60,13 @@ function initSelect() {
const userPassword2 = ce.userConfirmationPassEl.value
if (userPassword1 === '') {
alert('Prosim, vnesite geslo')
alert(i18next.t('Prosim, vnesite geslo'))
} else if (userPassword2 === '') {
alert('Prosim, ponovno vnesite geslo')
alert(i18next.t('Prosim, ponovno vnesite geslo'))
} else if (userPassword1 !== userPassword2) {
alert('Gesli se ne ujemata')
alert(i18next.t('Gesli se ne ujemata'))
} else {
alert('Gesli se ujemata!')
alert(i18next.t('Gesli se ujemata!'))
}
}
}
@@ -115,7 +115,7 @@ function deleteField(ele) {
// Summernote
$('.summernote').summernote({
placeholder: 'Na kratko opišite zasnovo in namen slovarja.',
placeholder: i18next.t('Na kratko opišite zasnovo in namen slovarja.'),
height: 300,
minheight: 150,
toolbar: [
@@ -1,4 +1,4 @@
/* global axios */
/* global axios, i18next */
/*
TODO
@@ -8,6 +8,8 @@ not just language filter, but filter for many properties...
/** BEGIN VARIABLE CONSTRUCTION AREA */
let allAggregationDataForSF = null
// TODO insert all sections of ids
const ids = [
'src-lang-side',
@@ -176,6 +178,10 @@ function cleanOldList() {
modalListRoot.innerHTML = ''
}
function setTitleOnModal(title) {
document.getElementById('modal-filter-label').innerHTML = title
}
async function selectMoreListener(event) {
const idstring = `${event.currentTarget.id
.replace('select-', '')
@@ -183,12 +189,17 @@ async function selectMoreListener(event) {
.concat('-side')}`
// console.log(extractMap(idstring))
const titleText =
event.currentTarget.parentElement.parentElement.children[0].textContent
setTitleOnModal(titleText)
// mp is the array of the currently displayed filters (required to get the checked information)
// const mp = initializedValues[idstring]
// all filters for search
// const allAggregationData = { id: idstring }
const allAggregationData = { id: idstring }
allAggregationDataForSF = { id: idstring }
const currentURL = new URL(window.location.href)
const searchParams = currentURL.searchParams
@@ -200,10 +211,10 @@ async function selectMoreListener(event) {
// const parsed = JSON.parse(event.currentTarget.dataset.aggregationInfo ?? '[]')
allAggregationData.items = data[idToSearchFiltersMapper(idstring)]
allAggregationDataForSF.items = data[idToSearchFiltersMapper(idstring)]
cleanOldList()
initModalList(allAggregationData.id, allAggregationData.items)
initModalList(allAggregationDataForSF.id, allAggregationDataForSF.items)
}
function idToSearchFiltersMapper(inpt) {
@@ -297,6 +308,18 @@ function finishSelectingFromModal(e) {
window.location.href = url
}
function finishSelectingFromModal2(e) {
const url = new URL(window.location.href)
const searchParams = url.searchParams
searchParams.delete(queryOrderedArr[sectionIDBattery])
selectedIds[sectionIDBattery].forEach(e => {
searchParams.append(queryOrderedArr[sectionIDBattery], e)
})
window.location.href = url
}
function reRenderSpecific(event) {
const idstring = event.currentTarget.id
const id = idstring.replace('show-all-', '')
@@ -349,7 +372,7 @@ function rePlotAndCheck(sectionId, selectedIdsArray, plotInverse = false) {
const img = document.createElement('img')
img.setAttribute('src', '/images/chevron-left-blue.svg')
const span = document.createElement('span')
span.innerHTML = 'PRIKAŽI VSE'
span.innerHTML = i18next.t('PRIKAŽI VSE')
anchr.appendChild(img)
anchr.appendChild(span)
@@ -378,6 +401,7 @@ function clearModalFilters() {
e.children[0].children[0].checked = false
})
selectedIds[sectionIDBattery] = []
clearSnapshots()
}
function clearModalFiltersWID(id) {
@@ -402,7 +426,7 @@ function initializeClickables() {
.addEventListener('click', selectFromModal)
document
.querySelector('#sf-modal-button')
.addEventListener('click', finishSelectingFromModal)
.addEventListener('click', finishSelectingFromModal2)
document.querySelector('#ccf').addEventListener('click', clearModalFilters)
@@ -428,6 +452,40 @@ function initializeClickables() {
// initModalList('id1', langsMapModal)
function filterModalEntries(event) {
cleanOldList()
// console.log(allAggregationDataForSF.items)
const prompt = document.getElementById('filterSfmText')
let filtered
if (prompt) {
filtered = allAggregationDataForSF.items.filter(item =>
item.name.toLowerCase().includes(prompt.value.toLowerCase())
)
} else {
return
}
initModalList(allAggregationDataForSF.id, filtered)
}
const sfmFilterButton = document.getElementById('filter-sfm')
const sfmOnEnterListener = document.querySelector('.onEnterListener')
if (sfmFilterButton) {
sfmFilterButton.addEventListener('click', filterModalEntries)
}
if (sfmOnEnterListener) {
sfmOnEnterListener.addEventListener('keyup', event => {
if (event.key === 'Enter') {
filterModalEntries(event)
}
})
}
/// global run
initializeClickables()
+14 -11
View File
@@ -70,20 +70,23 @@ function generateTooltipWithStyles(
) {
let nonEmptyContent
if (!content) {
nonEmptyContent = el => {
el.getAttribute('data-tooltip-content')
}
return generateTooltipBase(list, function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl, {
html: true,
title: tooltipTriggerEl.getAttribute('data-tooltip-content') || '',
customClass: styles
})
})
} else {
nonEmptyContent = content
}
return generateTooltipBase(list, function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl, {
html: true,
title: nonEmptyContent,
customClass: styles
return generateTooltipBase(list, function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl, {
html: true,
title: nonEmptyContent || '',
customClass: styles
})
})
})
}
}
function generateTooltipBase(list, fn) {
+3 -3
View File
@@ -1,4 +1,4 @@
/* global axios */
/* global axios, i18next */
function autoGrow(element) {
element.style.height = '5px'
@@ -156,14 +156,14 @@ function editRowBodyForConsultancy(fieldInfo) {
fieldInfo.newButtonGroup = newButtonGroup
fieldInfo.cancelButton = cancelButton
fieldInfo.saveButton = saveButton
cancelButton.textContent = 'Prekliči'
cancelButton.textContent = i18next.t('Prekliči')
cancelButton.className = 'btn btn-secondary me-2'
cancelButton.style.height = '33px'
cancelButton.style.width = '105px'
cancelButton.addEventListener('click', () =>
abortConsultancyUserEditing(fieldInfo)
)
saveButton.textContent = 'POTRDI'
saveButton.textContent = i18next.t('POTRDI')
saveButton.className = 'btn btn-primary'
saveButton.style.height = '33px'
saveButton.style.width = '105px'