Initial commit
This commit is contained in:
@@ -0,0 +1,222 @@
|
||||
/* global axios, bootstrap */
|
||||
const mainContainer = document.getElementById('offset-main')
|
||||
mainContainer.addEventListener('click', clickHandler)
|
||||
|
||||
function clickHandler({ target }) {
|
||||
const createPortalBtn = target.closest('.create-portal-btn')
|
||||
const linkPortalBtn = target.closest('.link-portal-btn')
|
||||
const syncPortalBtn = target.closest('.sync-portal-btn')
|
||||
const portalEnableSwitch = target.closest('.portal-enable-switch')
|
||||
const deleteTaskBtn = target.closest('.delete-task')
|
||||
if (createPortalBtn) {
|
||||
const indexURLEl = document.getElementById('index-url')
|
||||
const indexURL = indexURLEl.value
|
||||
createPortal(indexURL)
|
||||
}
|
||||
if (linkPortalBtn) {
|
||||
const linkedPortalId = linkPortalBtn.getAttribute('data-link-id')
|
||||
const closestTask = linkPortalBtn.closest('.task-declined')
|
||||
linkPortal(linkedPortalId, closestTask)
|
||||
}
|
||||
if (syncPortalBtn) {
|
||||
const linkedPortalId = syncPortalBtn.getAttribute('data-link-id')
|
||||
syncPortal(linkedPortalId)
|
||||
}
|
||||
if (portalEnableSwitch) {
|
||||
const portalId = portalEnableSwitch.getAttribute('data-portal-id')
|
||||
const isEnabled =
|
||||
portalEnableSwitch.querySelector('.form-check-input').checked
|
||||
updatePortalStatus(portalId, isEnabled)
|
||||
}
|
||||
if (deleteTaskBtn) {
|
||||
const alertModal = new bootstrap.Modal(
|
||||
document.getElementById('alert-modal')
|
||||
)
|
||||
alertModal.toggle()
|
||||
const taskId = deleteTaskBtn.getAttribute('data-link-id')
|
||||
const modalUseBtn = document.getElementById('modal-use-btn')
|
||||
modalUseBtn.addEventListener('click', deleteConnection(taskId))
|
||||
}
|
||||
}
|
||||
|
||||
async function createPortal(indexURL) {
|
||||
event.preventDefault()
|
||||
const form = document.getElementById('form-connection-new')
|
||||
const payload = new URLSearchParams(new FormData(form))
|
||||
try {
|
||||
const id = await axios.post('/api/v1/portals/createPortal', payload)
|
||||
await linkPortal(id.data[0].id)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
} finally {
|
||||
window.location.href = '../../../admin/povezave/seznam'
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteConnection(id) {
|
||||
try {
|
||||
await axios.delete(`/api/v1/portals/${id}/deleteLinkedDictionary`)
|
||||
alertModal.hide()
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function linkPortal(linkedPortalId, type) {
|
||||
try {
|
||||
const r = await axios.put(`/api/v1/portals/${linkedPortalId}/dictionaries`)
|
||||
// if (data.length) {
|
||||
// await insertPortalDictionaries(data, linkedPortalId)
|
||||
// if (type) {
|
||||
// changeContent(data, type)
|
||||
// }
|
||||
// }
|
||||
console.log(r)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function insertPortalDictionaries(data, portalId) {
|
||||
data.forEach(el => (el.linkedPortalId = portalId))
|
||||
try {
|
||||
// Ta enpoint je bil odstranjen, ker je itak nepotreben. Tudi ta funkcija je nepotrebna.
|
||||
// TODO Odstrani to funkcijo in prilagodi lokacije, kjer je sedaj klicana.
|
||||
// await axios.post('/api/v1/portals/insertDictionaries', {
|
||||
// params: { data }
|
||||
// })
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function syncPortal(linkedPortalId) {
|
||||
event.preventDefault()
|
||||
const responseModal = new bootstrap.Modal(
|
||||
document.getElementById('response-modal')
|
||||
)
|
||||
const responseModalText = document.getElementById('response-modal-text')
|
||||
try {
|
||||
axios
|
||||
.all([
|
||||
axios.put(`/api/v1/portals/${linkedPortalId}/dictionaries`),
|
||||
axios.get('/api/v1/portals/getMyDictionaries', {
|
||||
params: { id: linkedPortalId }
|
||||
})
|
||||
])
|
||||
.then(
|
||||
axios.spread((obj1, obj2) => {
|
||||
const theirDict = obj1.data
|
||||
const myDict = obj2.data
|
||||
|
||||
const results = theirDict.filter(
|
||||
({ id: id1 }) =>
|
||||
!myDict.some(({ target_dictionary_id: id2 }) => id2 === id1)
|
||||
)
|
||||
|
||||
responseModalText.textContent = `Spremenjenih je bilo ${results.length} slovarjev.`
|
||||
if (results.length) {
|
||||
insertPortalDictionaries(results, linkedPortalId)
|
||||
responseModal.toggle()
|
||||
} else {
|
||||
responseModal.toggle()
|
||||
}
|
||||
})
|
||||
)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
async function updatePortalStatus(portalId, isEnabled) {
|
||||
try {
|
||||
await axios.post('/api/v1/portals/updatePortalStatus', {
|
||||
params: { id: portalId, isEnabled: isEnabled }
|
||||
})
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
function changeContent(data, type) {
|
||||
const nameEl = document.querySelector('.bold-weight-black')
|
||||
const name = nameEl.textContent
|
||||
const indexURLEl = document.querySelector('.link-url')
|
||||
const indexURL = indexURLEl.textContent
|
||||
const imageLinkEl = document.querySelector('.link-portal-btn')
|
||||
const id = imageLinkEl.getAttribute('data-link-id')
|
||||
const syncedDiv = document.getElementById('synced-terms-div')
|
||||
const contaner2 = document.createElement('div')
|
||||
contaner2.className = 'd-sm-flex justify-content-sm-between d-grid'
|
||||
const gridEl = document.createElement('div')
|
||||
gridEl.className = 'd-grid'
|
||||
const spanCode = document.createElement('span')
|
||||
spanCode.className = 'bold-weight-black'
|
||||
spanCode.textContent = name
|
||||
const spanURL = document.createElement('span')
|
||||
spanURL.className = 'normal-gray mt-2.mb-2'
|
||||
spanURL.textContent = indexURL
|
||||
const centerDiv = document.createElement('div')
|
||||
centerDiv.className = 'd-flex align-items-center justify-content-sm-end'
|
||||
const btnDict = document.createElement('button')
|
||||
btnDict.className = 'btn btn-secondary align-items-center d-flex'
|
||||
const imgDict = document.createElement('img')
|
||||
const spanDict = document.createElement('span')
|
||||
spanDict.className = 'ms-1'
|
||||
const hr = document.createElement('hr')
|
||||
hr.className = 'mt-2 mb-3'
|
||||
const betweenEl = document.createElement('div')
|
||||
betweenEl.className = 'd-sm-flex justify-content-between'
|
||||
const alignCntEl = document.createElement('div')
|
||||
const alertDiv = document.createElement('div')
|
||||
alertDiv.className = 'd-flex align-content-center mb-0 me-3 mt-2 mt-sm-0'
|
||||
const alertmargin = document.createElement('div')
|
||||
alertmargin.className = 'ms-3'
|
||||
const deleteBtn = document.createElement('button')
|
||||
deleteBtn.className = 'p-0 btn delete-task'
|
||||
const deleteImg = document.createElement('img')
|
||||
deleteImg.src = '/images/red-trash-icon.svg'
|
||||
const spanDelete = document.createElement('span')
|
||||
spanDelete.className = 'normal-gray ms-2'
|
||||
spanDelete.textContent = 'Odstrani'
|
||||
|
||||
if (data.length) {
|
||||
const container = document.createElement('div')
|
||||
container.className = 'container-fluid task task-completed p-3 mb-4'
|
||||
const aDictEl = document.createElement('a')
|
||||
aDictEl.className = 'btn btn-secondary align-items-center d-flex'
|
||||
aDictEl.href = `/admin/povezave/seznam/${id}`
|
||||
imgDict.src = '/images/book-colorized.svg'
|
||||
spanDict.textContent = 'Slovarji'
|
||||
alignCntEl.className =
|
||||
'd-sm-flex align-items-center mb-0 form-check form-switch'
|
||||
const switchEl = document.createElement('input')
|
||||
switchEl.className = 'form-check-input'
|
||||
switchEl.type = 'checkbox'
|
||||
switchEl.name = 'isEnabled'
|
||||
switchEl.id = 'checkbox' + id
|
||||
const spanSwitch = document.createElement('span')
|
||||
spanSwitch.className = 'normal-gray ms-1 mt-1'
|
||||
spanSwitch.textContent = 'Omogočeno'
|
||||
|
||||
container.appendChild(contaner2)
|
||||
contaner2.appendChild(gridEl)
|
||||
gridEl.appendChild(spanCode)
|
||||
contaner2.appendChild(centerDiv)
|
||||
centerDiv.appendChild(aDictEl)
|
||||
aDictEl.appendChild(imgDict)
|
||||
aDictEl.appendChild(spanDict)
|
||||
container.appendChild(hr)
|
||||
container.appendChild(betweenEl)
|
||||
betweenEl.appendChild(alignCntEl)
|
||||
alignCntEl.appendChild(switchEl)
|
||||
alignCntEl.appendChild(spanSwitch)
|
||||
betweenEl.appendChild(alertDiv)
|
||||
alertDiv.appendChild(alertmargin)
|
||||
alertmargin.appendChild(deleteBtn)
|
||||
deleteBtn.appendChild(deleteImg)
|
||||
deleteBtn.appendChild(spanDelete)
|
||||
syncedDiv.appendChild(container)
|
||||
type.remove()
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
||||
{
|
||||
let isVisible = false
|
||||
const pager = document.querySelector('.pager')
|
||||
const commentsContainer = document.querySelector('#comments-container')
|
||||
const dropImage = document.querySelector('#dropImage')
|
||||
const commentCount = document.querySelector('#comments-count')
|
||||
|
||||
const hide = () => {
|
||||
pager.className += ' d-none'
|
||||
commentsContainer.className += ' d-none'
|
||||
commentCount.className += ' d-none'
|
||||
}
|
||||
|
||||
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'
|
||||
} else {
|
||||
dropImage.src = '/images/arrow_drop_down.svg'
|
||||
hide()
|
||||
}
|
||||
})
|
||||
|
||||
hide()
|
||||
}
|
||||
@@ -0,0 +1,651 @@
|
||||
// TODO Remove no-console ignore rule once things are out of rapid dev phase.
|
||||
/* eslint no-console: 0 */
|
||||
/* global axios, initPagination */
|
||||
const pageURL = location.pathname
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
initComments()
|
||||
})
|
||||
|
||||
function initComments() {
|
||||
const ce = {}
|
||||
ce.updatePager = initPagination('pagination', onPageChange)
|
||||
window.commentElements = ce
|
||||
ce.commentsCountEl = document.getElementById('comments-count')
|
||||
ce.commentsContainerEl = document.getElementById('comments-container')
|
||||
ce.commentForm = document.getElementById('comment-form')
|
||||
ce.commentReplyForm = document.getElementById('comment-reply-form')
|
||||
ce.commentMessageInput = document.getElementById('comment-message-input')
|
||||
ce.commentSubmitBtn = document.getElementById('comment-submit-btn')
|
||||
ce.commentReplyInput = document.getElementById('comment-reply-input')
|
||||
ce.commentQuoteId = document.getElementById('comment-quote-id')
|
||||
ce.commentSubmitReplyBtn = document.getElementById('comment-submit-reply-btn')
|
||||
ce.replyFormContainer = document.getElementById('reply-form-container')
|
||||
ce.replyCircle = document.getElementById('reply-circle')
|
||||
ce.commentDiv = document.querySelector('.comment-div')
|
||||
|
||||
ce.commentSubmitBtn &&
|
||||
ce.commentSubmitBtn.addEventListener('click', submitComment)
|
||||
// ce.commentMessageInput.addEventListener('keydown', messageInputClick)
|
||||
ce.commentsContainerEl &&
|
||||
ce.commentsContainerEl.addEventListener('click', handleCommentClick)
|
||||
ce.commentSubmitReplyBtn &&
|
||||
ce.commentSubmitReplyBtn.addEventListener('click', submitCommentReply)
|
||||
ce.commentMessageInput &&
|
||||
ce.commentMessageInput.addEventListener('input', autoGrow)
|
||||
ce.commentReplyInput &&
|
||||
ce.commentReplyInput.addEventListener('input', autoGrow)
|
||||
// ce.commentMessageInput.addEventListener('keydown', normalizeTextAreaSize)
|
||||
|
||||
window.commentSetting = {}
|
||||
window.commentSetting.localeOptions = {
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
}
|
||||
|
||||
if (ce.commentMessageInput && ce.commentReplyInput) {
|
||||
ce.commentMessageInput.originalHeight = window.getComputedStyle(
|
||||
ce.commentMessageInput
|
||||
).height
|
||||
ce.commentReplyInput.originalHeight = window.getComputedStyle(
|
||||
ce.commentReplyInput
|
||||
).height
|
||||
}
|
||||
|
||||
if (/\/slovarji\/\d+\/vsebina/.test(pageURL)) {
|
||||
ce.terminsList = document.getElementById('term-list')
|
||||
if (ce.terminsList) {
|
||||
ce.terminsList.addEventListener('click', displayComments)
|
||||
}
|
||||
const ctxBtns = document.getElementsByName('comments-type')
|
||||
if (ctxBtns) {
|
||||
const ctxBtnsArray = Array.from(ctxBtns)
|
||||
ctxBtnsArray.forEach(el => el.addEventListener('click', displayComments))
|
||||
}
|
||||
}
|
||||
ce.commentMessageInput && ce.commentReplyInput && clearMessageInput()
|
||||
displayComments()
|
||||
}
|
||||
|
||||
function autoGrow({ target: inputToResize }) {
|
||||
if (!inputToResize.value) {
|
||||
inputToResize.style.height = inputToResize.originalHeight
|
||||
} else {
|
||||
inputToResize.style.height = Math.min(inputToResize.scrollHeight, 95) + 'px'
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeTextAreaSize() {
|
||||
const { commentMessageInput } = window.commentElements
|
||||
commentMessageInput.style.height = commentMessageInput.originalHeight
|
||||
}
|
||||
|
||||
// function replyInputClick({ key }) {
|
||||
// if (key === 'Enter') {
|
||||
// const { commentSubmitReplyBtn } = window.commentElements
|
||||
// commentSubmitReplyBtn.click()
|
||||
// }
|
||||
// }
|
||||
|
||||
async function displayComments(page) {
|
||||
// TODO Add error handler
|
||||
const comments = await fetchComments(page)
|
||||
renderComments(comments)
|
||||
return comments
|
||||
}
|
||||
|
||||
async function fetchComments(page) {
|
||||
const ctxData = getCtxTypeId()
|
||||
let apiCall = '/api/v1/comments?ctx_type=' + ctxData.ctxType
|
||||
if (ctxData.ctxId !== undefined)
|
||||
apiCall = apiCall + '&' + 'ctx_id=' + ctxData.ctxId
|
||||
if (page) apiCall = apiCall + `&p=${page}`
|
||||
const res = await axios.get(apiCall)
|
||||
return res.data
|
||||
}
|
||||
|
||||
function renderComments(comments) {
|
||||
const oldComments = document.querySelectorAll('.comment')
|
||||
if (oldComments.length) {
|
||||
const arrayChildren = Array.from(oldComments)
|
||||
arrayChildren.forEach(el => el.remove())
|
||||
}
|
||||
renderCommentCount(comments.commentCount)
|
||||
comments.comments.forEach(comment => appendComment(comment))
|
||||
const pagesTotalEl = document.querySelector('.pages-total')
|
||||
|
||||
// TODO: Think of a better solution for buggy content pagination
|
||||
pagesTotalEl.textContent = comments.numberOfAllPages
|
||||
}
|
||||
|
||||
function renderCommentCount(commentCount) {
|
||||
const { commentsCountEl } = window.commentElements
|
||||
|
||||
let displayText = `${commentCount} `
|
||||
|
||||
// TODO Let a i18n library handle the following logic.
|
||||
switch (commentCount % 100) {
|
||||
case 1:
|
||||
displayText += 'komentar'
|
||||
break
|
||||
case 2:
|
||||
displayText += 'komentarja'
|
||||
break
|
||||
case 3:
|
||||
case 4:
|
||||
displayText += 'komentarji'
|
||||
break
|
||||
|
||||
default:
|
||||
displayText += 'komentarjev'
|
||||
break
|
||||
}
|
||||
|
||||
commentsCountEl.textContent = displayText
|
||||
}
|
||||
|
||||
function appendComment(comment) {
|
||||
const { commentsContainerEl, commentDiv } = window.commentElements
|
||||
const { localeOptions } = window.commentSetting
|
||||
|
||||
const {
|
||||
message,
|
||||
author: { firstName: authorFirstName, lastName: authorLastName },
|
||||
timeCreated,
|
||||
status,
|
||||
quote
|
||||
} = comment
|
||||
|
||||
let tstamp = new Date(timeCreated).toLocaleTimeString('sl-SL', localeOptions)
|
||||
|
||||
tstamp = `• ${tstamp}`
|
||||
const divText = document.createElement('div')
|
||||
const divTextComment = document.createElement('div')
|
||||
const divRow = document.createElement('div')
|
||||
const divRowHead = document.createElement('div')
|
||||
const liCommentContainer = document.createElement('li')
|
||||
const divCircle = document.createElement('div')
|
||||
const spanDate = document.createElement('span')
|
||||
const spanName = document.createElement('span')
|
||||
const spanInitials = document.createElement('span')
|
||||
const divCol = document.createElement('div')
|
||||
const aReply = document.createElement('button')
|
||||
const imgReplyBtn = document.createElement('img')
|
||||
const horizontalRowContainer = document.createElement('div')
|
||||
const horizontalRow = document.createElement('hr')
|
||||
|
||||
divTextComment.className = 'comment-text-2'
|
||||
|
||||
divRow.className = 'row'
|
||||
|
||||
divRowHead.className = 'row'
|
||||
|
||||
divText.className = 'comment-text'
|
||||
|
||||
liCommentContainer.className = 'comment'
|
||||
liCommentContainer.dataObject = comment
|
||||
|
||||
divCircle.className = 'comment-initials-container'
|
||||
|
||||
spanInitials.className = 'test'
|
||||
|
||||
divCol.className = 'comment-col col'
|
||||
|
||||
spanName.className = 'comment-author-name'
|
||||
|
||||
spanDate.className = 'comment-date'
|
||||
|
||||
aReply.className = 'comment-reply-btn'
|
||||
imgReplyBtn.src = '/images/fi_corner-down-left.svg'
|
||||
imgReplyBtn.alt = 'Reply'
|
||||
|
||||
horizontalRowContainer.className = 'horizontal-row-container container-l'
|
||||
horizontalRow.className = 'comment-hr comment-line'
|
||||
|
||||
const firstNameInitial = authorFirstName.slice(0, 1)
|
||||
const lastNameInitial = authorLastName.slice(0, 1)
|
||||
|
||||
const initialLetters = `${firstNameInitial}${lastNameInitial}`
|
||||
spanInitials.textContent = initialLetters
|
||||
|
||||
spanDate.textContent = tstamp
|
||||
|
||||
const authorName = `${authorFirstName} ${authorLastName}`
|
||||
spanName.textContent = authorName
|
||||
|
||||
divTextComment.textContent = message
|
||||
|
||||
if (quote) {
|
||||
const {
|
||||
message,
|
||||
author: { firstName: authorFirstName, lastName: authorLastName },
|
||||
timeCreated
|
||||
} = quote
|
||||
|
||||
let tstamp = new Date(timeCreated).toLocaleTimeString(
|
||||
'sl-SL',
|
||||
localeOptions
|
||||
)
|
||||
|
||||
tstamp = `• ${tstamp}`
|
||||
|
||||
const quoteText = document.createElement('div')
|
||||
const imgQuotemarks = document.createElement('img')
|
||||
const spanQuoteName = document.createElement('span')
|
||||
const spanQuoteDate = document.createElement('span')
|
||||
const divQuotedText = document.createElement('div')
|
||||
const quotehr = document.createElement('hr')
|
||||
|
||||
quoteText.className = 'comment-text-2'
|
||||
|
||||
imgQuotemarks.src = '/images/quote-marks.svg'
|
||||
|
||||
spanQuoteName.className = 'comment-quotename'
|
||||
|
||||
spanQuoteDate.className = 'comment-quotedate'
|
||||
|
||||
divQuotedText.className = 'comment-quotedtext'
|
||||
|
||||
quotehr.className = 'comment-quotehr'
|
||||
|
||||
spanQuoteDate.innerText = tstamp
|
||||
|
||||
const authorName = `${authorFirstName} ${authorLastName}`
|
||||
|
||||
spanQuoteName.textContent = authorName
|
||||
|
||||
divQuotedText.textContent = message
|
||||
|
||||
divText.appendChild(quoteText)
|
||||
quoteText.appendChild(imgQuotemarks)
|
||||
quoteText.appendChild(spanQuoteName)
|
||||
quoteText.appendChild(spanQuoteDate)
|
||||
quoteText.appendChild(divQuotedText)
|
||||
divQuotedText.appendChild(quotehr)
|
||||
}
|
||||
commentsContainerEl.insertBefore(liCommentContainer, commentDiv)
|
||||
liCommentContainer.appendChild(divRowHead)
|
||||
divRowHead.appendChild(divCircle)
|
||||
divCircle.appendChild(spanInitials)
|
||||
divRowHead.appendChild(divCol)
|
||||
divCol.appendChild(spanName)
|
||||
divCol.appendChild(spanDate)
|
||||
divCol.appendChild(aReply)
|
||||
aReply.appendChild(imgReplyBtn)
|
||||
liCommentContainer.appendChild(divRow)
|
||||
divRow.appendChild(divText)
|
||||
divText.appendChild(divTextComment)
|
||||
divRow.appendChild(horizontalRowContainer)
|
||||
horizontalRowContainer.appendChild(horizontalRow)
|
||||
if (comment.showEye) {
|
||||
const btnSeen = document.createElement('button')
|
||||
const imgSeen = document.createElement('img')
|
||||
|
||||
divCol.appendChild(btnSeen)
|
||||
btnSeen.appendChild(imgSeen)
|
||||
if (status === 'visible') {
|
||||
btnSeen.className = 'comment-seen-btn me-2'
|
||||
imgSeen.src = '/images/eye.svg'
|
||||
imgSeen.alt = 'Viden'
|
||||
} else {
|
||||
btnSeen.className = 'comment-eye-off-btn me-2'
|
||||
imgSeen.src = '/images/eye-off.svg'
|
||||
imgSeen.alt = 'Skrit'
|
||||
}
|
||||
}
|
||||
if (status === 'hidden') whitenCommentText(liCommentContainer)
|
||||
else normalCommentColors(liCommentContainer)
|
||||
}
|
||||
|
||||
function submitComment() {
|
||||
const { commentMessageInput } = window.commentElements
|
||||
|
||||
const message = commentMessageInput.value
|
||||
const ctxData = getCtxTypeId()
|
||||
const ctxType = ctxData.ctxType
|
||||
let ctxId = null
|
||||
if (ctxData.ctxId !== undefined) ctxId = ctxData.ctxId
|
||||
if (!message) {
|
||||
alert('Vaš komentar je brez vsebine.')
|
||||
} else {
|
||||
const payload = { message, ctxType, ctxId, quoteId: null }
|
||||
createComment(payload)
|
||||
}
|
||||
normalizeTextAreaSize()
|
||||
}
|
||||
|
||||
function submitCommentReply() {
|
||||
const { commentReplyInput, commentQuoteId } = window.commentElements
|
||||
const message = commentReplyInput.value
|
||||
const ctxData = getCtxTypeId()
|
||||
const ctxType = ctxData.ctxType
|
||||
const quoteId = commentQuoteId.value
|
||||
let ctxId = null
|
||||
if (ctxData.ctxId !== undefined) ctxId = ctxData.ctxId
|
||||
if (!message) {
|
||||
alert('Vaš komentar je brez vsebine.')
|
||||
} else {
|
||||
const payload = { message, ctxType, ctxId, quoteId }
|
||||
createComment(payload)
|
||||
}
|
||||
}
|
||||
|
||||
async function createComment(comment) {
|
||||
const { updatePager } = window.commentElements
|
||||
try {
|
||||
const res = await axios.post('/api/v1/comments', comment)
|
||||
const { comments, pagesTotal } = res.data
|
||||
handleCommentSubmissionSuccess(comments)
|
||||
updatePager(pagesTotal, pagesTotal)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
handleCommentSubmissionError()
|
||||
}
|
||||
}
|
||||
|
||||
function handleCommentSubmissionSuccess(comments) {
|
||||
const { commentForm, replyFormContainer } = window.commentElements
|
||||
|
||||
commentForm.classList.remove('hide')
|
||||
replyFormContainer.classList.add('hide')
|
||||
clearMessageInput()
|
||||
const commentQuoteContent = document.getElementById('comment-quote-content')
|
||||
if (commentQuoteContent) commentQuoteContent.remove()
|
||||
const oldComments = document.querySelectorAll('.comment')
|
||||
if (oldComments.length) {
|
||||
const arrayChildren = Array.from(oldComments)
|
||||
arrayChildren.forEach(el => el.remove())
|
||||
}
|
||||
// renderCommentCount(comments.comments.length)
|
||||
comments.forEach(comment => appendComment(comment))
|
||||
}
|
||||
|
||||
function clearMessageInput() {
|
||||
const { commentMessageInput, commentReplyInput } = window.commentElements
|
||||
|
||||
commentMessageInput.value = ''
|
||||
commentReplyInput.value = ''
|
||||
}
|
||||
|
||||
function handleCommentSubmissionError() {
|
||||
console.error("Comment couldn't be saved. Handle appropriately")
|
||||
}
|
||||
|
||||
function handleCommentClick({ target }) {
|
||||
const replyButtonEl = target.closest('.comment-reply-btn')
|
||||
const btnSeenEl = target.closest('.comment-seen-btn')
|
||||
const btnEyeOffEl = target.closest('.comment-eye-off-btn')
|
||||
const commentData = target.closest('.comment')?.dataObject
|
||||
let status
|
||||
if (replyButtonEl) {
|
||||
prepareReplyForm(commentData)
|
||||
} else if (btnSeenEl) {
|
||||
const commentText = target.closest('.comment')
|
||||
whitenCommentText(commentText, btnSeenEl)
|
||||
status = 'hidden'
|
||||
commentVisibility(commentData.id, status)
|
||||
} else if (btnEyeOffEl) {
|
||||
const commentText = target.closest('.comment')
|
||||
normalCommentColors(commentText, btnEyeOffEl)
|
||||
status = 'visible'
|
||||
commentVisibility(commentData.id, status)
|
||||
}
|
||||
}
|
||||
|
||||
function prepareReplyForm(repliedCommentData) {
|
||||
const {
|
||||
id: quoteId,
|
||||
message: quoteMessage,
|
||||
author: { firstName: quoteAuthorFirstName, lastName: quoteAuthorLastName },
|
||||
timeCreated: quotetimeCreated
|
||||
} = repliedCommentData
|
||||
|
||||
window.scrollTo(0, document.body.scrollHeight)
|
||||
const { commentForm, commentReplyForm, commentQuoteId, replyFormContainer } =
|
||||
window.commentElements
|
||||
const { localeOptions } = window.commentSetting
|
||||
|
||||
commentQuoteId.value = quoteId
|
||||
|
||||
const oldQuotePreview = document.getElementById('comment-quote-content')
|
||||
if (oldQuotePreview) oldQuotePreview.remove()
|
||||
|
||||
commentForm.classList.add('hide')
|
||||
replyFormContainer.classList.remove('hide')
|
||||
|
||||
const quotePreview = document.createElement('div')
|
||||
quotePreview.id = 'comment-quote-content'
|
||||
|
||||
const quoteMarksEl = document.createElement('img')
|
||||
quoteMarksEl.src = '/images/quote-marks.svg'
|
||||
quoteMarksEl.id = 'quote-marks'
|
||||
quotePreview.appendChild(quoteMarksEl)
|
||||
|
||||
const quoteAuthorFirstNameEl = document.createElement('p')
|
||||
quoteAuthorFirstNameEl.className = 'comment-quote-author-fname'
|
||||
quoteAuthorFirstNameEl.textContent = quoteAuthorFirstName
|
||||
quotePreview.appendChild(quoteAuthorFirstNameEl)
|
||||
|
||||
const quoteAuthorLastNameEl = document.createElement('p')
|
||||
quoteAuthorLastNameEl.className = 'comment-quote-author-lname'
|
||||
quoteAuthorLastNameEl.textContent = quoteAuthorLastName
|
||||
quotePreview.appendChild(quoteAuthorLastNameEl)
|
||||
|
||||
let tstamp = new Date(quotetimeCreated).toLocaleTimeString(
|
||||
'sl-SL',
|
||||
localeOptions
|
||||
)
|
||||
|
||||
tstamp = `• ${tstamp}`
|
||||
const quotetimeCreatedEl = document.createElement('p')
|
||||
quotetimeCreatedEl.className = 'comment-quote-time-created'
|
||||
quotetimeCreatedEl.textContent = tstamp
|
||||
quotePreview.appendChild(quotetimeCreatedEl)
|
||||
|
||||
const shortenQuoteMessage = quoteMessage.substring(0, 175)
|
||||
const quoteMessageEl = document.createElement('p')
|
||||
quoteMessageEl.className = 'comment-quote-message'
|
||||
quoteMessageEl.textContent = shortenQuoteMessage
|
||||
quotePreview.appendChild(quoteMessageEl)
|
||||
|
||||
const horizontalLineEl = document.createElement('hr')
|
||||
horizontalLineEl.className = 'comment-reply-line'
|
||||
|
||||
quotePreview.appendChild(horizontalLineEl)
|
||||
|
||||
// commentReplyForm.insertBefore(quotePreview, commentReplyInput)
|
||||
replyFormContainer.insertBefore(quotePreview, commentReplyForm)
|
||||
|
||||
const commentReplyInputEl = document.getElementById('comment-reply-input')
|
||||
commentReplyInputEl.focus()
|
||||
commentReplyInputEl.select()
|
||||
}
|
||||
|
||||
async function commentVisibility(id, status) {
|
||||
try {
|
||||
await axios.post('/api/v1/comments/updateStatus', {
|
||||
params: { id, status }
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
handleCommentSubmissionError()
|
||||
}
|
||||
}
|
||||
|
||||
function whitenCommentText(selectedText, btnSeenEl) {
|
||||
if (btnSeenEl) {
|
||||
const imgEyeEl = btnSeenEl.lastElementChild
|
||||
imgEyeEl.src = '/images/eye-off.svg'
|
||||
btnSeenEl.classList.remove('comment-seen-btn')
|
||||
btnSeenEl.classList.add('comment-eye-off-btn')
|
||||
}
|
||||
selectedText.classList.add('comment-white-text')
|
||||
}
|
||||
|
||||
function normalCommentColors(selectedText, btnEyeOffEl) {
|
||||
if (btnEyeOffEl) {
|
||||
const imgEyeEl = btnEyeOffEl.lastElementChild
|
||||
imgEyeEl.src = '/images/eye.svg'
|
||||
btnEyeOffEl.classList.add('comment-seen-btn')
|
||||
btnEyeOffEl.classList.remove('comment-eye-off')
|
||||
}
|
||||
selectedText.classList.remove('comment-white-text')
|
||||
}
|
||||
|
||||
// function getCtxId({ target }) {
|
||||
// console.log(target)
|
||||
// const termBtn = target.closest('.terms-label')
|
||||
// console.log(termBtn)
|
||||
// if (termBtn) {
|
||||
// console.log(termBtn)
|
||||
// displayComments()
|
||||
// }
|
||||
// }
|
||||
|
||||
const ctxBtns = document.getElementsByName('comments-type')
|
||||
const commentsTab = document.getElementById('content-comments')
|
||||
if (ctxBtns) {
|
||||
const ctxBtnsArray = Array.from(ctxBtns)
|
||||
ctxBtnsArray.forEach(el => el.addEventListener('click', displayComments))
|
||||
}
|
||||
if (commentsTab) {
|
||||
commentsTab.addEventListener('click', displayComments)
|
||||
}
|
||||
|
||||
function getCtxTypeId(type) {
|
||||
const { terminsList } = window.commentElements
|
||||
let ctxType
|
||||
let ctxId
|
||||
const splitURL = pageURL.split('/')
|
||||
if (location.pathname !== '/') {
|
||||
if (!pageURL.match('admin/komentarji')) ctxId = pageURL.match(/\d+/)[0]
|
||||
if (type) ctxId = type
|
||||
}
|
||||
splitURL.forEach(el => {
|
||||
if (el === 'slovarji') {
|
||||
ctxType = 'dictionary'
|
||||
}
|
||||
if (el === 'admin') {
|
||||
ctxType = 'portal'
|
||||
}
|
||||
/* "vebina" -> in case this endpoint is used anywhere in the future,
|
||||
delete this legacy endpint matching otherwise */
|
||||
if (el === 'vsebina') {
|
||||
const selected = checkButton('intext')
|
||||
if (selected === 'internal') ctxType = 'entry_dict_int'
|
||||
if (selected === 'external') ctxType = 'entry_dict_ext'
|
||||
const selectedTerm = checkButton(terminsList)
|
||||
ctxId = selectedTerm
|
||||
}
|
||||
if (el === 'termin') {
|
||||
ctxType = 'entry_dict_ext'
|
||||
ctxId = checkButtonModular('returnFromEntryDetail')
|
||||
}
|
||||
if (el === 'urejanje') {
|
||||
ctxType = 'entry_consult_int'
|
||||
ctxId = checkButtonModular('returnFromCosnultancyInternal')
|
||||
}
|
||||
})
|
||||
if (location.pathname === '/') {
|
||||
ctxType = 'portal'
|
||||
ctxId = null
|
||||
}
|
||||
|
||||
return { ctxType: ctxType, ctxId: ctxId }
|
||||
}
|
||||
|
||||
function checkButton(type) {
|
||||
let checked
|
||||
if (type === 'intext') {
|
||||
checked = document.querySelector('input[name="comments-type"]:checked').id
|
||||
} else {
|
||||
const term = document.querySelector('.selected-term-btn')
|
||||
if (term) {
|
||||
const termId = term.getAttribute('data-term-id')
|
||||
checked = termId
|
||||
}
|
||||
}
|
||||
return checked
|
||||
}
|
||||
|
||||
async function onPageChange(newPage) {
|
||||
const { updatePager } = window.commentElements
|
||||
try {
|
||||
const { page, numberOfAllPages } = await displayComments(newPage)
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* improved version of checkButton function
|
||||
*
|
||||
* @param {*} type
|
||||
* Parameter that checks whether the selector should choose:
|
||||
* -> if 'intext' -> returns internal or external comment type
|
||||
* -> if namePattern = returnFrom[Dictionary | Entry | OtherName]Detail
|
||||
* | -> returns context ID from URL depending on its location
|
||||
* -> else -> returns the context ID of the selected TERM (also known as entry)
|
||||
* (previous fn compatible)
|
||||
* @param {*} selectorExternal
|
||||
* Parameter that defines from which element to read the ID in case type
|
||||
* isn't "intext". Please notice that the attribute for id is not id, but
|
||||
* data-term-id
|
||||
* @param {*} selectorInternal
|
||||
* Parameter that defines where to read the string "internal" or "external"
|
||||
* in case of type being "intext"
|
||||
* @returns
|
||||
*
|
||||
* #Note to the author of the fn: Please define function such that
|
||||
* one function only does one job, not nested into different logic
|
||||
* based on a string.
|
||||
*/
|
||||
function checkButtonModular(
|
||||
type,
|
||||
selectorExternal = '.selected-term-btn',
|
||||
selectorInternal = 'input[name="comments-type"]:checked'
|
||||
) {
|
||||
let checked
|
||||
if (type === 'intext') {
|
||||
checked = document.querySelector(selectorInternal).id
|
||||
} else if (type === 'returnFromEntryDetail') {
|
||||
checked = returnCommentCTXFromParsedURL(type)
|
||||
} else if (type === 'returnFromCosnultancyInternal') {
|
||||
checked = returnCommentCTXFromParsedURL(type)
|
||||
} else {
|
||||
const term = document.querySelector(selectorExternal)
|
||||
if (term) {
|
||||
const termId = term.getAttribute('data-term-id')
|
||||
checked = termId
|
||||
}
|
||||
}
|
||||
return checked
|
||||
}
|
||||
|
||||
function returnCommentCTXFromParsedURL(typeOfURL) {
|
||||
let retString = 'Undefined - please check your code'
|
||||
if (typeOfURL === 'returnFromEntryDetail') {
|
||||
const splitStringBat = window.location.href.split('/')
|
||||
retString = splitStringBat[splitStringBat.length - 1]
|
||||
} else if (typeOfURL === 'returnFromDictionaryDetail') {
|
||||
const splitStringBat = window.location.href.split('/')
|
||||
retString = splitStringBat[splitStringBat.length - 2]
|
||||
} else if (typeOfURL === 'returnFromCosnultancyInternal') {
|
||||
const splitStringBat = window.location.href.split('/')
|
||||
retString = splitStringBat[splitStringBat.length - 1].split('?')[0]
|
||||
}
|
||||
|
||||
// console.log('ID: ' + retString)
|
||||
return retString
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/* global $, axios */
|
||||
|
||||
function sumbitFormForConsultancy(e) {
|
||||
const id = document.querySelector('#entry-id').value
|
||||
const questionTitle = document.querySelector('#question-title').value
|
||||
const domain = document.querySelector('#select-cerif').value
|
||||
const question = document.querySelector('#question').value
|
||||
const answer = $('#opinion').summernote('code')
|
||||
|
||||
axios.put(e.target.action, {
|
||||
id,
|
||||
questionTitle,
|
||||
domain,
|
||||
question,
|
||||
answer
|
||||
})
|
||||
axios
|
||||
.put('/api/v1/consultancy/entry', {
|
||||
id,
|
||||
questionTitle,
|
||||
domain,
|
||||
question,
|
||||
answer
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href = '/svetovanje/vprasanje/admin/v-delu'
|
||||
})
|
||||
}
|
||||
|
||||
{
|
||||
/*
|
||||
$('#opinion').summernote({
|
||||
codeviewFilter: true,
|
||||
codeviewIframeFilter: true
|
||||
})
|
||||
*/
|
||||
|
||||
const ef = document.querySelector('#edit-form')
|
||||
|
||||
ef.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
|
||||
sumbitFormForConsultancy(e)
|
||||
})
|
||||
|
||||
ef.addEventListener('change', e => {
|
||||
document.querySelector('#opt1').disabled = false
|
||||
})
|
||||
|
||||
$('#opinion').on('summernote.change', function (we, contents, $editable) {
|
||||
document.querySelector('#opt1').disabled = false
|
||||
})
|
||||
|
||||
const resizeFields = document.querySelectorAll('.explanation-field')
|
||||
if (resizeFields.length) {
|
||||
resizeFields.forEach(el =>
|
||||
el.addEventListener('input', () => autoResize(el))
|
||||
)
|
||||
}
|
||||
|
||||
function autoResize(el) {
|
||||
if (el.style) {
|
||||
el.style.height = 42 + 'px'
|
||||
el.style.height = `${el.scrollHeight}px`
|
||||
}
|
||||
}
|
||||
|
||||
resizeFields.forEach(el => {
|
||||
autoResize(el)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* global $ , unsavedData, sumbitFormForConsultancy */
|
||||
|
||||
const form = document.getElementById('edit-form')
|
||||
const sideMenu = document.querySelector('.admin-nav-content')
|
||||
|
||||
unsavedData(form, sideMenu, sumbitFormForConsultancy)
|
||||
@@ -0,0 +1,67 @@
|
||||
/* global $, inputMainSearch */
|
||||
|
||||
const searchButton = document.getElementById('couns-search-btn')
|
||||
const advancedSearchButton = document.getElementById('search-in-filter-modal')
|
||||
|
||||
function routeConsultancy(searchString) {
|
||||
let url
|
||||
|
||||
if (searchString) {
|
||||
url = new URL(searchString, location.protocol + '//' + location.host)
|
||||
} else {
|
||||
url = new URL(location)
|
||||
|
||||
const sq = document.getElementById('search-query')
|
||||
if (sq) {
|
||||
url.searchParams.set('q', sq.value)
|
||||
}
|
||||
}
|
||||
// const qParams = new URL(location).searchParams
|
||||
|
||||
// error prone code because of clear filter
|
||||
// qParams.forEach((value, key) => {
|
||||
// if (key !== 'q') {
|
||||
// url.searchParams.append(key, value)
|
||||
// }
|
||||
// })
|
||||
const pds = $('.select-domain-field')
|
||||
if (pds) {
|
||||
pds.val().forEach(val => {
|
||||
url.searchParams.append('pd', val)
|
||||
})
|
||||
}
|
||||
|
||||
window.location.href = url
|
||||
}
|
||||
|
||||
function searchOnConsultancyBaseOrAdmin() {
|
||||
const isItNotAdminURL = !location.pathname.includes('/admin/')
|
||||
|
||||
if (isItNotAdminURL) {
|
||||
const sq = document.getElementById('search-query')
|
||||
routeConsultancy(`/svetovanje/iskanje?q=${sq ? sq.value : ''}`)
|
||||
} else {
|
||||
// build here URL for admin sections
|
||||
routeConsultancy(null)
|
||||
}
|
||||
}
|
||||
|
||||
function propagateFunctionalityToASearchButton(el) {
|
||||
if (el) {
|
||||
el.addEventListener('click', searchOnConsultancyBaseOrAdmin)
|
||||
}
|
||||
}
|
||||
|
||||
if (inputMainSearch) {
|
||||
const listenForTypingOnConsultancy = function (event) {
|
||||
if (event.code === 'Enter') {
|
||||
event.preventDefault()
|
||||
searchOnConsultancyBaseOrAdmin() // here you invoke the function since it is not a listener
|
||||
}
|
||||
}
|
||||
|
||||
inputMainSearch.addEventListener('keyup', listenForTypingOnConsultancy)
|
||||
}
|
||||
|
||||
propagateFunctionalityToASearchButton(searchButton)
|
||||
propagateFunctionalityToASearchButton(advancedSearchButton)
|
||||
@@ -0,0 +1,440 @@
|
||||
/* global $, handleDomainsClickForConsultancy, inputFieldsChecker, currentPagePath, axios, nthParent, tooltipListWOL, tooltipTriggerList */
|
||||
|
||||
/*
|
||||
author: Miha Stele, 2022
|
||||
*/
|
||||
|
||||
/** selectedID -> ID of the selected Entry */
|
||||
let selectedID = -1
|
||||
|
||||
// consultancy FORM
|
||||
let offsetMain
|
||||
function adjustOffsetBy() {
|
||||
offsetMain = document.querySelector('#offset-main')
|
||||
const fixedTopSection = document.querySelector('#fixed-top-section')
|
||||
const referenceHeight = fixedTopSection.offsetHeight
|
||||
const offsetHeader = document.getElementsByClassName('offset-header')
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
// const adminNavMobile = document.getElementsByClassName('admin-nav')
|
||||
const headerPadding = document.getElementById('header-padding')
|
||||
|
||||
if (document.body.clientWidth < 1200) {
|
||||
if (offsetHeaderPadding !== null) offsetMain.style.paddingTop = `0px`
|
||||
} else {
|
||||
for (let i = 0; i < offsetHeader.length; i++) {
|
||||
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
if (headerPadding !== null) {
|
||||
const headerPaddingHeight = headerPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${headerPaddingHeight}px`
|
||||
}
|
||||
if (offsetHeaderPadding !== null) {
|
||||
const offsetHeaderHeight = offsetHeaderPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${referenceHeight + offsetHeaderHeight}px`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function event2SelectedId(e) {
|
||||
return nthParent(e.currentTarget, 4).id.substring(3)
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
adjustOffsetBy()
|
||||
|
||||
const ce = {}
|
||||
window.adminElements = ce
|
||||
/* copy source admin.js in case of refactoring */
|
||||
|
||||
if (currentPagePath === '/svetovanje/vprasanje/admin/uporabniki') {
|
||||
offsetMain.addEventListener('click', handleDomainsClickForConsultancy)
|
||||
ce.name = document.getElementById('name-input')
|
||||
if (ce.name) {
|
||||
ce.name.addEventListener('input', inputFieldsChecker)
|
||||
}
|
||||
ce.inputAreaEl = document.getElementById('area-input')
|
||||
if (ce.inputAreaEl) {
|
||||
ce.inputAreaEl.addEventListener('input', inputFieldsChecker)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
adjustOffsetBy()
|
||||
// mobileMoveContent()
|
||||
})
|
||||
|
||||
try {
|
||||
document.querySelector('#consultancy-form').addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
|
||||
// window.location.replace('/svetovanje/iskanje')
|
||||
})
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
const splitedHref = window.location.href.split('/')
|
||||
|
||||
document.querySelectorAll('.edit-button').forEach(e => {
|
||||
e.addEventListener('click', () => {
|
||||
window.location.replace(
|
||||
`/svetovanje/vprasanje/admin/urejanje/${nthParent(e, 4).id.slice(
|
||||
3
|
||||
)}?sentFrom=${splitedHref[splitedHref.length - 1]}`
|
||||
)
|
||||
})
|
||||
})
|
||||
} catch (e) {}
|
||||
// share.pug
|
||||
try {
|
||||
// In your Javascript (external .js resource or <script> tag)
|
||||
$(document).ready(function () {
|
||||
$('.share-search-consultants').select2({
|
||||
dropdownParent: $('#consultancyModalShare')
|
||||
})
|
||||
})
|
||||
} catch (e) {}
|
||||
|
||||
// assign.pug
|
||||
try {
|
||||
// In your Javascript (external .js resource or <script> tag)
|
||||
$(document).ready(function () {
|
||||
$('.assign-search-consultants').select2({
|
||||
dropdownParent: $('#consultancyModalAssign')
|
||||
})
|
||||
})
|
||||
} catch (e) {}
|
||||
|
||||
const summernote = $('.summernote')
|
||||
if (summernote) {
|
||||
summernote.summernote({
|
||||
placeholder: 'Na kratko opišite zasnovo in namen slovarja.',
|
||||
height: 300,
|
||||
minheight: 150,
|
||||
toolbar: [
|
||||
['style', ['style', 'bold', 'italic', 'underline']],
|
||||
['font', ['superscript', 'subscript']],
|
||||
['link', ['linkDialogShow']],
|
||||
['para', ['ul', 'ol']],
|
||||
['table', ['table']],
|
||||
['insert', ['picture']]
|
||||
],
|
||||
styleTags: ['p', 'h3', 'h4']
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
mixin shareResultsItem(userId, name)
|
||||
.share-results-item(id=userId)
|
||||
.row
|
||||
.col-11
|
||||
p.mb-0.navigation-text-color.mb0 #{ name }
|
||||
.col-1
|
||||
.d-flex.justify-content-end
|
||||
button.delete-shared-cons.bg-transparent.no-border
|
||||
img(src="/images/trash-2.svg")
|
||||
hr.mt-1.mb-1
|
||||
*/
|
||||
function buildSharedAuthorListItem(id, name) {
|
||||
const root = document.createElement('div')
|
||||
root.className = 'share-results-item'
|
||||
root.id = id
|
||||
const row = document.createElement('div')
|
||||
row.className = 'row'
|
||||
root.appendChild(row)
|
||||
const hr = document.createElement('hr')
|
||||
hr.className = 'mt-1 mb-1'
|
||||
root.appendChild(hr)
|
||||
const col11 = document.createElement('div')
|
||||
col11.className = 'col-11'
|
||||
row.appendChild(col11)
|
||||
const col1 = document.createElement('div')
|
||||
col1.className = 'col-1'
|
||||
row.appendChild(col1)
|
||||
const nameEl = document.createElement('p')
|
||||
nameEl.className = 'mb-0 navigation-text-color mb0'
|
||||
nameEl.textContent = name
|
||||
col11.appendChild(nameEl)
|
||||
const aligner = document.createElement('div')
|
||||
aligner.className = 'd-flex justify-content-end'
|
||||
col1.appendChild(aligner)
|
||||
const btn = document.createElement('btn')
|
||||
btn.className = 'delete-shared-cons bg-transparent no-border'
|
||||
aligner.appendChild(btn)
|
||||
const img = document.createElement('img')
|
||||
img.src = '/images/trash-2.svg'
|
||||
btn.appendChild(img)
|
||||
|
||||
btn.addEventListener('click', e => {
|
||||
const element = nthParent(e.currentTarget, 4)
|
||||
|
||||
axios
|
||||
.delete('/api/v1/consultancy/delete-consultant-author', {
|
||||
data: {
|
||||
question_id: selectedID,
|
||||
user_id: element.id
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
element.remove()
|
||||
})
|
||||
})
|
||||
|
||||
root.appendChild(row)
|
||||
|
||||
return root
|
||||
}
|
||||
|
||||
const assignModalBtns = document.querySelectorAll('.consultancy-modal-assign')
|
||||
|
||||
// assign button logic NOTE you can only have assignBtn when you have
|
||||
// assign buttons (one or more) that trigger the assign modal (assignModalBtns)
|
||||
// otherwise they're useless
|
||||
if (assignModalBtns.length > 0) {
|
||||
// let modalQuestionBatteryId = -1
|
||||
|
||||
assignModalBtns.forEach(assignButton => {
|
||||
assignButton.addEventListener('click', e => {
|
||||
$('#consultancyModalAssign').modal('toggle')
|
||||
selectedID = parseInt(event2SelectedId(e))
|
||||
})
|
||||
})
|
||||
|
||||
const assignBtn = document.querySelector('#assign-btn')
|
||||
|
||||
if (assignBtn) {
|
||||
assignBtn.addEventListener('click', e => {
|
||||
// TODO, assign the question to the in progress section if you are consultancy admin or portal admin
|
||||
|
||||
const userId = document.querySelector('#assign-sel').value
|
||||
if (userId !== 'NONE_SELECTED_PLACEHOLDER') {
|
||||
axios
|
||||
.put('/api/v1/consultancy/assign', {
|
||||
question_id: selectedID,
|
||||
user_id: document.querySelector('#assign-sel').value
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href += ''
|
||||
})
|
||||
} else {
|
||||
console.log('Please select different username')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const shareButtons = document.querySelectorAll('.consultancy-modal-share')
|
||||
|
||||
if (shareButtons.length > 0) {
|
||||
document.querySelector('#add-shared-author').addEventListener('click', () => {
|
||||
axios
|
||||
.post('/api/v1/consultancy/add-non-moderator', {
|
||||
question_id: selectedID,
|
||||
user_id: document.querySelector('#share-sel').value
|
||||
})
|
||||
.then(e => {
|
||||
const sel = document.querySelector('#share-sel')
|
||||
document
|
||||
.querySelector('.share-results-container')
|
||||
.appendChild(
|
||||
buildSharedAuthorListItem(
|
||||
selectedID,
|
||||
sel.options[sel.selectedIndex].text
|
||||
)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
document.querySelector('#close-shared').addEventListener('click', () => {
|
||||
window.location.href += ''
|
||||
})
|
||||
|
||||
shareButtons.forEach(assignButton => {
|
||||
assignButton.addEventListener('click', e => {
|
||||
selectedID = parseInt(event2SelectedId(e))
|
||||
axios
|
||||
.get(`/api/v1/consultancy/get-shared-authors?id=${selectedID}`)
|
||||
.then(res => {
|
||||
const rootCont = document.querySelector('.share-results-container')
|
||||
rootCont.innerHTML = ''
|
||||
|
||||
const authors = res.data
|
||||
authors.forEach(author => {
|
||||
rootCont.appendChild(
|
||||
buildSharedAuthorListItem(
|
||||
author.user_id,
|
||||
`${author.first_name} ${author.last_name} (${author.username})`
|
||||
)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
$('#consultancyModalShare').modal('toggle')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const rejectButtons = document.querySelectorAll('.reject-item')
|
||||
|
||||
if (rejectButtons.length > 0) {
|
||||
rejectButtons.forEach(rejectButton => {
|
||||
rejectButton.addEventListener('click', e => {
|
||||
selectedID = parseInt(event2SelectedId(e))
|
||||
// $('#alert-modal').modal('toggle')
|
||||
|
||||
axios
|
||||
.put('/api/v1/consultancy/reject', {
|
||||
question_id: selectedID
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href += ''
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const deleteButtons = document.querySelectorAll('.delete-item')
|
||||
|
||||
if (deleteButtons.length > 0) {
|
||||
document.querySelector('#del-btn').addEventListener('click', e => {
|
||||
axios
|
||||
.delete('/api/v1/consultancy/delete', {
|
||||
data: { id: selectedID }
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href += ''
|
||||
})
|
||||
})
|
||||
|
||||
deleteButtons.forEach(assignButton => {
|
||||
assignButton.addEventListener('click', e => {
|
||||
selectedID = parseInt(event2SelectedId(e))
|
||||
$('#deleteModal').modal('toggle')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const reviewBtns = document.querySelectorAll('.review-btn')
|
||||
|
||||
if (reviewBtns.length > 0) {
|
||||
reviewBtns.forEach(reviewBtn => {
|
||||
reviewBtn.addEventListener('click', e => {
|
||||
selectedID = parseInt(event2SelectedId(e))
|
||||
|
||||
axios
|
||||
.put('/api/v1/consultancy/review', {
|
||||
question_id: selectedID
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href += ''
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const publishBtns = document.querySelectorAll('.publish-btn')
|
||||
|
||||
if (publishBtns.length > 0) {
|
||||
publishBtns.forEach(publishBtn => {
|
||||
publishBtn.addEventListener('click', e => {
|
||||
selectedID = parseInt(event2SelectedId(e))
|
||||
|
||||
const answerAuthorsWithComma =
|
||||
document.getElementById('moderatorName').innerText +
|
||||
',' +
|
||||
(nthParent(
|
||||
e.currentTarget,
|
||||
3
|
||||
).childNodes[0].childNodes[0].childNodes[4].getAttribute(
|
||||
'data-tooltip-content'
|
||||
) ?? ',')
|
||||
axios
|
||||
.put('/api/v1/consultancy/publish', {
|
||||
question_id: selectedID,
|
||||
answer_authors: answerAuthorsWithComma.slice(0, -1)
|
||||
})
|
||||
.then(() => {
|
||||
window.location.href += ''
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// Share authors boilerplate code
|
||||
|
||||
/// // SUBMIT FUNCTIONS
|
||||
|
||||
const createAnswerForm = document.querySelector('#create-consultancy-question')
|
||||
|
||||
if (createAnswerForm) {
|
||||
async function onCreateAnswerSubmit(event) {
|
||||
event.preventDefault()
|
||||
if (createAnswerForm && !createAnswerForm.checkValidity()) {
|
||||
event.stopPropagation()
|
||||
createAnswerForm.classList.add('was-validated')
|
||||
return
|
||||
}
|
||||
|
||||
const payload = Object.fromEntries(new FormData(event.target))
|
||||
|
||||
const res = await axios.post(event.target.action, payload)
|
||||
// const data = res.data
|
||||
|
||||
// console.log(data)
|
||||
|
||||
if (res.status === 201) {
|
||||
window.location.href = '/svetovanje'
|
||||
}
|
||||
}
|
||||
|
||||
createAnswerForm.addEventListener('submit', onCreateAnswerSubmit)
|
||||
}
|
||||
|
||||
const insertConsultantForm = document.querySelector('#insert-consultant')
|
||||
|
||||
if (insertConsultantForm) {
|
||||
insertConsultantForm.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
const url = e.currentTarget.action
|
||||
|
||||
const username = document.querySelector('#username').value
|
||||
const domains = document.querySelector('#domains').value
|
||||
|
||||
axios
|
||||
.post(url, {
|
||||
username: username,
|
||||
domains: domains
|
||||
})
|
||||
.then(result => {
|
||||
console.log(result)
|
||||
window.location.href = '/svetovanje/vprasanje/admin/uporabniki'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
if (tooltipTriggerList.length > 0) {
|
||||
// initialize tooltips
|
||||
tooltipListWOL('author-list-tooltip') // ADD for tooltip debug in the end -> [0].show()
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
/*
|
||||
if (tooltipList) {
|
||||
console.log(tooltipList)
|
||||
tooltipList.forEach(ptl => {
|
||||
console.log(ptl)
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
// focus required field section
|
||||
|
||||
$(document).ready(() => {
|
||||
const focused = $('#description')
|
||||
if (focused) {
|
||||
focused.focus()
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,172 @@
|
||||
/* global axios */
|
||||
|
||||
// Priporočam uporabo block scopa okoli paginacijske logike za čimvečjo izolacijo.
|
||||
{
|
||||
// Referenca na element, kamor se izrisuje seznam rezultatov.
|
||||
const resultsListEl = document.getElementById('page-results')
|
||||
|
||||
// Paginacijo inicializiraš s klicem funkcije initPagination:
|
||||
// 1. parameter: id pager elementa. V demo-paginacija.pug je to #pagination.
|
||||
// 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)
|
||||
|
||||
// Fukncija, prejme številko nove strani in naj:
|
||||
// 1. Pridobi podatke nove strani.
|
||||
// 2. Izriše seznam elementov te strani.
|
||||
// 3. Posodobi pager, tako, da kliče funkcijo, ki jo je vrnil klic initPagination (updateDemoPager) z novo stranjo in številom vseh strani.
|
||||
async function onPageChange(newPage) {
|
||||
try {
|
||||
const { page, numberOfAllPages, results } = await getDataForPage(newPage)
|
||||
removeAllChildNodes(resultsListEl)
|
||||
renderResults(results)
|
||||
updateDemoPager(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)
|
||||
updateDemoPager()
|
||||
}
|
||||
}
|
||||
|
||||
// Primer helper funkcije za pridobitev podatkov želene strani.
|
||||
async function getDataForPage(page) {
|
||||
const url = `/api/v1/demo-paginacija/list?p=${page}`
|
||||
const { data } = await axios.get(url)
|
||||
return data
|
||||
}
|
||||
|
||||
// Primer helper funkcije za izris seznama novih podatkov.
|
||||
function renderResults(results) {
|
||||
results.forEach(result => {
|
||||
const newListEl = document.createElement('li')
|
||||
const textNode1 = document.createTextNode('Zanimiva vrednost: ')
|
||||
const boldedEl = document.createElement('b')
|
||||
boldedEl.textContent = result.zanimivo
|
||||
const textNode2 = document.createTextNode(
|
||||
`. Totalno nezanimivo: ${result.nezanimivo1} in ${result.nezanimivo2}`
|
||||
)
|
||||
|
||||
newListEl.append(textNode1, boldedEl, textNode2)
|
||||
resultsListEl.appendChild(newListEl)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/** ****************************************************************************************************************************************** **\
|
||||
* Koda od tu navzdol za vaju ni relevantna. Tu je, da dela zgornja koda. Za realno uporabo sem je skopiral tudi v public/javascripts/scripts.js *
|
||||
* 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')
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return updatePagerUi
|
||||
}
|
||||
|
||||
// Helper function to easily remove all child nodes. Useful for pagination.
|
||||
function removeAllChildNodes(parent) {
|
||||
while (parent.firstChild) {
|
||||
parent.removeChild(parent.firstChild)
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,72 @@
|
||||
/* global axios, initPagination, removeAllChildNodes */
|
||||
{
|
||||
const selectorEl = document.getElementById('select-extraction-name')
|
||||
selectorEl.addEventListener('change', () => loadCandidates(selectorEl.value))
|
||||
const resultsListEl = document.getElementById('page-results')
|
||||
let termCandidates
|
||||
let hitsPerPage
|
||||
let numberOfAllPages
|
||||
async function loadCandidates(id) {
|
||||
try {
|
||||
const { data } = await axios.get(
|
||||
`/api/v1/extraction/${id}/term-candidates`
|
||||
)
|
||||
termCandidates = data.termCandidates
|
||||
hitsPerPage = data.hitsPerPage
|
||||
numberOfAllPages = data.numberOfAllPages
|
||||
removeAllChildNodes(resultsListEl)
|
||||
const results = getDataForFirstPage(data)
|
||||
renderResults(results)
|
||||
updateDemoPager(1, numberOfAllPages)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
|
||||
const updateDemoPager = initPagination('pagination', onPageChange)
|
||||
|
||||
function onPageChange(newPage) {
|
||||
const results = getDataForPage(newPage)
|
||||
removeAllChildNodes(resultsListEl)
|
||||
renderResults(results)
|
||||
updateDemoPager(newPage, numberOfAllPages)
|
||||
}
|
||||
|
||||
function getDataForPage(page) {
|
||||
const sliceStart = (page - 1) * hitsPerPage
|
||||
const sliceEnd = page * hitsPerPage
|
||||
const onePageOfTermCandidates = termCandidates.slice(sliceStart, sliceEnd)
|
||||
const data = onePageOfTermCandidates.map((candidate, index) => {
|
||||
const sequentialCount = sliceStart + index + 1
|
||||
return [sequentialCount, candidate]
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
function getDataForFirstPage() {
|
||||
const sliceStart = (1 - 1) * hitsPerPage
|
||||
const sliceEnd = 1 * hitsPerPage
|
||||
const onePageOfTermCandidates = termCandidates.slice(sliceStart, sliceEnd)
|
||||
const data = onePageOfTermCandidates.map((candidate, index) => {
|
||||
const sequentialCount = sliceStart + index + 1
|
||||
return [sequentialCount, candidate]
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
function renderResults(results) {
|
||||
results.forEach(([sequentialCount, candidate]) => {
|
||||
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')
|
||||
tdId.textContent = sequentialCount
|
||||
tdName.textContent = candidate.kanonicnaoblika
|
||||
tdSize.textContent = candidate.ranking
|
||||
tdDate.textContent = candidate.pogostostpojavljanja
|
||||
rowEl.append(tdId, tdName, tdSize, tdDate)
|
||||
resultsListEl.appendChild(rowEl)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/* global axios, removeAllChildNodes, bootstrap */
|
||||
|
||||
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
|
||||
|
||||
dragButton.onclick = () => {
|
||||
dragInput.click()
|
||||
}
|
||||
|
||||
dragInput.addEventListener('change', function () {
|
||||
file = this.files[0]
|
||||
dropArea.classList.add('active')
|
||||
// showFile(file)
|
||||
})
|
||||
|
||||
dropArea.addEventListener('dragover', event => {
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
dropArea.addEventListener('dragleave', () => {})
|
||||
|
||||
dropArea.addEventListener('drop', event => {
|
||||
event.preventDefault()
|
||||
fileInputEl.files = event.dataTransfer.files
|
||||
submitFiles()
|
||||
})
|
||||
|
||||
// offsetMain.addEventListener('click', handleClick)
|
||||
|
||||
// function handleClick({ target }) {
|
||||
// const row = target.closest('.delete-btn-table')
|
||||
// if (row) {
|
||||
// deleteRow(row)
|
||||
// }
|
||||
|
||||
// function deleteRow(ele) {
|
||||
// // console.log(ele)
|
||||
// const element = ele.closest('tr')
|
||||
// element.remove()
|
||||
// }
|
||||
// }
|
||||
|
||||
const extractionId = +fileUploadForm.extractionId.value
|
||||
let apiEndpointBase
|
||||
switch (location.pathname.split('/').at(-1)) {
|
||||
case 'besedila':
|
||||
apiEndpointBase = `/api/v1/extraction/${extractionId}/documents`
|
||||
break
|
||||
|
||||
case 'stop-termini':
|
||||
apiEndpointBase = `/api/v1/extraction/${extractionId}/stop-terms`
|
||||
break
|
||||
|
||||
default:
|
||||
throw Error("apiEndpointBase couldn't be determined")
|
||||
}
|
||||
|
||||
fileInputEl.addEventListener('change', submitFiles)
|
||||
filesListEl.addEventListener('click', handleFileClick)
|
||||
|
||||
async function submitFiles() {
|
||||
// TODO Lock additional submits for the duration of this function execution?
|
||||
const MAX_FILE_SIZE = 10 ** 9 // 1 GB
|
||||
const failedUploads = []
|
||||
|
||||
modalSpinner.toggle()
|
||||
|
||||
for (const file of fileInputEl.files) {
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
const failedUpload = {
|
||||
filename: file.name,
|
||||
message: 'File too large. Must not be over 1 GB.'
|
||||
}
|
||||
failedUploads.push(failedUpload)
|
||||
continue
|
||||
}
|
||||
|
||||
const payload = new FormData()
|
||||
payload.set(fileInputEl.name, file)
|
||||
try {
|
||||
await axios.put(apiEndpointBase, payload)
|
||||
} catch (error) {
|
||||
const failedUpload = {
|
||||
filename: file.name,
|
||||
message: error.response.data
|
||||
}
|
||||
failedUploads.push(failedUpload)
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
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 displayFailedUploads(failedUploads) {
|
||||
failedUploads.forEach(({ filename, message }) => {
|
||||
const alertText = modalAlert.querySelector('#alert-text')
|
||||
alertText.textContent = `NAPAKA - Ime datoteke: ${filename}, razlog: ${message}`
|
||||
modalAlert.toggle()
|
||||
})
|
||||
}
|
||||
|
||||
async function handleFileClick(e) {
|
||||
if (e.target.closest('.delete-file')) {
|
||||
const fileEl = e.target.closest('tr')
|
||||
const filename = fileEl.querySelector('.filename').textContent
|
||||
try {
|
||||
await axios.delete(`${apiEndpointBase}/${filename}`)
|
||||
fileEl.remove()
|
||||
} catch {
|
||||
alert('Pri brisanju datoteke je prišlo do napake.')
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* global axios, bootstrap */
|
||||
|
||||
const extractionListEl = document.getElementById('extraction-list')
|
||||
|
||||
extractionListEl.addEventListener('click', onListClick)
|
||||
|
||||
async function onListClick({ target }) {
|
||||
if (target.closest('.btn-delete')) {
|
||||
const extractionEl = target.closest('.task')
|
||||
const extractionId = extractionEl.dataset.id
|
||||
const alertModal = new bootstrap.Modal(
|
||||
document.getElementById('alert-modal')
|
||||
)
|
||||
alertModal.toggle()
|
||||
const modalUseBtn = document.getElementById('modal-use-btn')
|
||||
modalUseBtn.addEventListener('click', async () => {
|
||||
await axios.delete(`/api/v1/extraction/${extractionId}`)
|
||||
extractionEl.remove()
|
||||
})
|
||||
} else if (target.classList.contains('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')
|
||||
)
|
||||
responseModal.toggle()
|
||||
} else if (target.classList.contains('btn-duplicate')) {
|
||||
const extractionEl = target.closest('.task')
|
||||
const extractionId = extractionEl.dataset.id
|
||||
await axios.post(`/api/v1/extraction/${extractionId}/duplicate`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/* global $, axios, bootstrap */
|
||||
|
||||
$('.pick-multiple').select2()
|
||||
$('.enter-multiple').select2({
|
||||
tags: true
|
||||
})
|
||||
|
||||
const editStopTermsLink = document.getElementById('edit-stop-terms')
|
||||
const searchButton = document.getElementById('search-btn')
|
||||
const searchResultEl = document.getElementById('search-result')
|
||||
const taskResultEl = document.querySelector('.task')
|
||||
const resultsCountEl = taskResultEl.querySelector('#results-count')
|
||||
const formEl = document.getElementById('form-edit-oss')
|
||||
const extractionId = +location.pathname.split('/').at(-1)
|
||||
const modalSpinner = new bootstrap.Modal(
|
||||
document.getElementById('modal-spinner')
|
||||
)
|
||||
const modalAlert = new bootstrap.Modal(document.getElementById('alert-modal'))
|
||||
|
||||
editStopTermsLink.addEventListener('click', saveOssParamsFirst)
|
||||
searchButton.addEventListener('click', handleSearch)
|
||||
searchResultEl.addEventListener('click', handleSearchResultsClick)
|
||||
|
||||
async function saveOssParamsFirst() {
|
||||
const payload = new URLSearchParams(new FormData(formEl))
|
||||
navigator.sendBeacon(
|
||||
`/api/v1/extraction/${extractionId}/oss-save-params`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
async function handleSearch() {
|
||||
modalSpinner.toggle()
|
||||
try {
|
||||
const { data } = await submitSearch()
|
||||
displaySearchResults(data)
|
||||
} catch {
|
||||
handleSearchError()
|
||||
}
|
||||
modalSpinner.toggle()
|
||||
}
|
||||
|
||||
function handleSearchError() {
|
||||
const alertText = modalAlert.querySelector('#alert-text')
|
||||
alertText.textContent = `NAPAKA pri iskanju`
|
||||
modalAlert.toggle()
|
||||
}
|
||||
|
||||
async function submitSearch() {
|
||||
const payload = new URLSearchParams(new FormData(formEl))
|
||||
return await axios.put(
|
||||
`/api/v1/extraction/${extractionId}/oss-search`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
function displaySearchResults({ documentCount, canSave }) {
|
||||
resultsCountEl.textContent = `${documentCount}`
|
||||
if (canSave) {
|
||||
const saveButton = taskResultEl.querySelector('.btn')
|
||||
saveButton.disabled = false
|
||||
}
|
||||
taskResultEl.classList.remove('d-none')
|
||||
}
|
||||
|
||||
function handleSearchResultsClick({ target }) {
|
||||
if (target.closest('#save-params')) confirmParams()
|
||||
}
|
||||
|
||||
async function confirmParams() {
|
||||
modalSpinner.toggle()
|
||||
try {
|
||||
await axios.put(`/api/v1/extraction/${extractionId}/oss-confirm-params`)
|
||||
location = '/luscenje'
|
||||
} catch {
|
||||
alert('Error saving params')
|
||||
modalSpinner.toggle()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/* global axios */
|
||||
|
||||
const fileUploadForm = document.forms['upload-files']
|
||||
const fileInputEl = fileUploadForm.querySelector('input[type="file"]')
|
||||
const messageContainerEl = document.getElementById('messages')
|
||||
const filesListEl = document.getElementById('files-list')
|
||||
|
||||
const extractionId = +fileUploadForm.extractionId.value
|
||||
let apiEndpointBase
|
||||
switch (location.pathname.split('/').at(-1)) {
|
||||
case 'besedila':
|
||||
apiEndpointBase = `/api/v1/extraction/${extractionId}/documents`
|
||||
break
|
||||
|
||||
case 'stop-termini':
|
||||
apiEndpointBase = `/api/v1/extraction/${extractionId}/stop-terms`
|
||||
break
|
||||
|
||||
default:
|
||||
throw Error("apiEndpointBase couldn't be determined")
|
||||
}
|
||||
|
||||
fileInputEl.addEventListener('change', submitFiles)
|
||||
filesListEl.addEventListener('click', handleFileClick)
|
||||
|
||||
async function submitFiles() {
|
||||
// TODO Lock additional submits for the duration of this function execution?
|
||||
const MAX_FILE_SIZE = 10 ** 9 // 1 GB
|
||||
const failedUploads = []
|
||||
|
||||
displaySpinner()
|
||||
|
||||
for (const file of fileInputEl.files) {
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
const failedUpload = {
|
||||
filename: file.name,
|
||||
message: 'File too large. Must not be over 1 GB.'
|
||||
}
|
||||
failedUploads.push(failedUpload)
|
||||
continue
|
||||
}
|
||||
|
||||
const payload = new FormData()
|
||||
payload.set(fileInputEl.name, file)
|
||||
try {
|
||||
await axios.put(apiEndpointBase, payload)
|
||||
} catch (error) {
|
||||
const failedUpload = {
|
||||
filename: file.name,
|
||||
message: error.response.data
|
||||
}
|
||||
failedUploads.push(failedUpload)
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
hideSpinner()
|
||||
}
|
||||
|
||||
function displaySpinner() {
|
||||
const messageEl = document.createElement('li')
|
||||
messageEl.textContent = 'Spinner on'
|
||||
messageContainerEl.appendChild(messageEl)
|
||||
}
|
||||
|
||||
function hideSpinner() {
|
||||
const messageEl = document.createElement('li')
|
||||
messageEl.textContent = 'Spinner off'
|
||||
messageContainerEl.appendChild(messageEl)
|
||||
}
|
||||
|
||||
function updateFilesList(files) {
|
||||
removeAllChildNodes(filesListEl)
|
||||
files.forEach(({ filename, size, timeModified }) => {
|
||||
const fileEl = document.createElement('li')
|
||||
const filenameSpanEl = document.createElement('span')
|
||||
filenameSpanEl.className = 'filename'
|
||||
filenameSpanEl.textContent = filename
|
||||
const formattedDate = new Date(timeModified).toLocaleDateString('sl-SL')
|
||||
const deleteButtonEl = document.createElement('a')
|
||||
deleteButtonEl.className = 'delete-file'
|
||||
deleteButtonEl.href = '#'
|
||||
deleteButtonEl.textContent = 'BRIŠI'
|
||||
fileEl.append(
|
||||
'DATOTEKA - Ime: ',
|
||||
filenameSpanEl,
|
||||
`, velikost: ${size}, datum: ${formattedDate} `,
|
||||
deleteButtonEl
|
||||
)
|
||||
filesListEl.appendChild(fileEl)
|
||||
})
|
||||
}
|
||||
|
||||
function displayFailedUploads(failedUploads) {
|
||||
failedUploads.forEach(({ filename, message }) => {
|
||||
const messageEl = document.createElement('li')
|
||||
messageEl.textContent = `NAPAKA - Ime datoteke: ${filename}, razlog: ${message}`
|
||||
messageContainerEl.appendChild(messageEl)
|
||||
})
|
||||
}
|
||||
|
||||
async function handleFileClick(e) {
|
||||
if (e.target.closest('.delete-file')) {
|
||||
const fileEl = e.target.closest('li')
|
||||
const filename = fileEl.querySelector('.filename').textContent
|
||||
try {
|
||||
await axios.delete(`${apiEndpointBase}/${filename}`)
|
||||
fileEl.remove()
|
||||
} catch {
|
||||
alert('Pri brisanju datoteke je prišlo do napake.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Don't copy this one into final JS. It's already defined in scripts.js
|
||||
function removeAllChildNodes(parent) {
|
||||
while (parent.firstChild) {
|
||||
parent.removeChild(parent.firstChild)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/* global axios */
|
||||
|
||||
const extractionListEl = document.getElementById('extraction-list')
|
||||
|
||||
extractionListEl.addEventListener('click', onListClick)
|
||||
|
||||
async function onListClick({ target }) {
|
||||
if (target.classList.contains('btn-delete')) {
|
||||
const extractionEl = target.closest('li')
|
||||
const extractionId = extractionEl.dataset.id
|
||||
await axios.delete(`/api/v1/extraction/${extractionId}`)
|
||||
extractionEl.remove()
|
||||
} else if (target.classList.contains('btn-begin')) {
|
||||
const extractionEl = target.closest('li')
|
||||
const extractionId = extractionEl.dataset.id
|
||||
await axios.put(`/api/v1/extraction/${extractionId}/begin`)
|
||||
} else if (target.classList.contains('btn-duplicate')) {
|
||||
const extractionEl = target.closest('li')
|
||||
const extractionId = extractionEl.dataset.id
|
||||
await axios.post(`/api/v1/extraction/${extractionId}/duplicate`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/* global $, axios */
|
||||
|
||||
$('.pick-multiple').select2()
|
||||
$('.enter-multiple').select2({
|
||||
tags: true
|
||||
})
|
||||
|
||||
const editStopTermsLink = document.getElementById('edit-stop-terms')
|
||||
const searchButton = document.getElementById('search-btn')
|
||||
const searchResultEl = document.getElementById('search-result')
|
||||
const messageContainerEl = document.getElementById('messages')
|
||||
const formEl = document.forms[0]
|
||||
const extractionId = +location.pathname.split('/').at(-1)
|
||||
|
||||
editStopTermsLink.addEventListener('click', saveOssParamsFirst)
|
||||
searchButton.addEventListener('click', handleSearch)
|
||||
searchResultEl.addEventListener('click', handleSearchResultsClick)
|
||||
|
||||
async function saveOssParamsFirst() {
|
||||
const payload = new URLSearchParams(new FormData(formEl))
|
||||
navigator.sendBeacon(
|
||||
`/api/v1/extraction/${extractionId}/oss-save-params`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
async function handleSearch() {
|
||||
displaySpinner()
|
||||
try {
|
||||
const { data } = await submitSearch()
|
||||
displaySearchResults(data)
|
||||
} catch {
|
||||
handleSearchError()
|
||||
}
|
||||
hideSpinner()
|
||||
}
|
||||
|
||||
function displaySpinner() {
|
||||
const messageEl = document.createElement('li')
|
||||
messageEl.textContent = 'Spinner on'
|
||||
messageContainerEl.appendChild(messageEl)
|
||||
}
|
||||
|
||||
function hideSpinner() {
|
||||
const messageEl = document.createElement('li')
|
||||
messageEl.textContent = 'Spinner off'
|
||||
messageContainerEl.appendChild(messageEl)
|
||||
}
|
||||
|
||||
function handleSearchError() {
|
||||
const messageEl = document.createElement('li')
|
||||
messageEl.textContent = 'Notify the user of error that occured during search'
|
||||
messageContainerEl.appendChild(messageEl)
|
||||
}
|
||||
|
||||
async function submitSearch() {
|
||||
const payload = new URLSearchParams(new FormData(formEl))
|
||||
return await axios.put(
|
||||
`/api/v1/extraction/${extractionId}/oss-search`,
|
||||
payload
|
||||
)
|
||||
}
|
||||
|
||||
function displaySearchResults({ documentCount, canSave }) {
|
||||
removeAllChildNodes(searchResultEl)
|
||||
searchResultEl.textContent = `Število dokumentov: ${documentCount}`
|
||||
if (canSave) {
|
||||
const saveButton = document.createElement('button')
|
||||
saveButton.id = 'save-params'
|
||||
saveButton.textContent = 'Shrani'
|
||||
searchResultEl.append(saveButton)
|
||||
}
|
||||
}
|
||||
|
||||
function handleSearchResultsClick({ target }) {
|
||||
if (target.closest('#save-params')) confirmParams()
|
||||
}
|
||||
|
||||
async function confirmParams() {
|
||||
displaySpinner()
|
||||
try {
|
||||
await axios.put(`/api/v1/extraction/${extractionId}/oss-confirm-params`)
|
||||
location = '../poc'
|
||||
} catch {
|
||||
alert('Error saving params')
|
||||
hideSpinner()
|
||||
}
|
||||
}
|
||||
|
||||
// Don't copy this one into final JS. It's already defined in scripts.js
|
||||
function removeAllChildNodes(parent) {
|
||||
while (parent.firstChild) {
|
||||
parent.removeChild(parent.firstChild)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/* global termCandidates, hitsPerPage, numberOfAllPages */
|
||||
{
|
||||
const resultsListEl = document.getElementById('page-results')
|
||||
|
||||
const updateDemoPager = initPagination('pagination', onPageChange)
|
||||
|
||||
function onPageChange(newPage) {
|
||||
const results = getDataForPage(newPage)
|
||||
removeAllChildNodes(resultsListEl)
|
||||
renderResults(results)
|
||||
updateDemoPager(newPage, numberOfAllPages)
|
||||
}
|
||||
|
||||
function getDataForPage(page) {
|
||||
const sliceStart = (page - 1) * hitsPerPage
|
||||
const sliceEnd = page * hitsPerPage
|
||||
const onePageOfTermCandidates = termCandidates.slice(sliceStart, sliceEnd)
|
||||
const data = onePageOfTermCandidates.map((candidate, index) => {
|
||||
const sequentialCount = sliceStart + index + 1
|
||||
return [sequentialCount, candidate]
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
function renderResults(results) {
|
||||
results.forEach(([sequentialCount, candidate]) => {
|
||||
const newListEl = document.createElement('li')
|
||||
newListEl.textContent = `[${sequentialCount}] ${JSON.stringify(
|
||||
candidate
|
||||
)}`
|
||||
resultsListEl.appendChild(newListEl)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Below code is copied from scripts.js, so it will already be available on the real page. No need to copy it there also.
|
||||
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')
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return updatePagerUi
|
||||
}
|
||||
|
||||
// Helper function to easily remove all child nodes. Useful for pagination.
|
||||
function removeAllChildNodes(parent) {
|
||||
while (parent.firstChild) {
|
||||
parent.removeChild(parent.firstChild)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* global termCandidates, hitsPerPage, numberOfAllPages, initPagination, removeAllChildNodes */
|
||||
{
|
||||
const resultsListEl = document.getElementById('page-results')
|
||||
|
||||
const updateDemoPager = initPagination('pagination', onPageChange)
|
||||
|
||||
function onPageChange(newPage) {
|
||||
const results = getDataForPage(newPage)
|
||||
removeAllChildNodes(resultsListEl)
|
||||
renderResults(results)
|
||||
updateDemoPager(newPage, numberOfAllPages)
|
||||
}
|
||||
|
||||
function getDataForPage(page) {
|
||||
const sliceStart = (page - 1) * hitsPerPage
|
||||
const sliceEnd = page * hitsPerPage
|
||||
const onePageOfTermCandidates = termCandidates.slice(sliceStart, sliceEnd)
|
||||
const data = onePageOfTermCandidates.map((candidate, index) => {
|
||||
const sequentialCount = sliceStart + index + 1
|
||||
return [sequentialCount, candidate]
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
function renderResults(results) {
|
||||
results.forEach(([sequentialCount, candidate]) => {
|
||||
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')
|
||||
tdId.textContent = sequentialCount
|
||||
tdName.textContent = candidate.kanonicnaoblika
|
||||
tdSize.textContent = candidate.ranking
|
||||
tdDate.textContent = candidate.pogostostpojavljanja
|
||||
rowEl.append(tdId, tdName, tdSize, tdDate)
|
||||
resultsListEl.appendChild(rowEl)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/* global currentPagePath */
|
||||
|
||||
// const currentPagePath = location.pathname
|
||||
|
||||
// Temporary workaround (use of currentPagePath).
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
initExtraction()
|
||||
})
|
||||
|
||||
function initExtraction() {
|
||||
const ce = {}
|
||||
window.extractionElements = ce
|
||||
ce.textDescription = document.getElementById('text-description')
|
||||
ce.headerTitle = document.getElementById('site-header-title')
|
||||
ce.headerRoot = document.getElementById('header-root')
|
||||
ce.fixedTopSection = document.getElementById('fixed-top-section')
|
||||
ce.topContainer = document.getElementsByClassName('top-container')[0]
|
||||
ce.offsetMain = document.getElementById('offset-main')
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
adjustOffsetBy()
|
||||
mobileMoveContent()
|
||||
})
|
||||
mobileMoveContent()
|
||||
adjustOffsetBy()
|
||||
window.onscroll = hideAndShowHeader
|
||||
|
||||
function hideAndShowHeader() {
|
||||
const { textDescription, headerTitle } = window.extractionElements
|
||||
|
||||
if (document.body.clientWidth >= 1200) {
|
||||
if (document.documentElement.scrollTop < 50) {
|
||||
textDescription.style.display = 'block'
|
||||
headerTitle.style.display = 'block'
|
||||
} else {
|
||||
textDescription.style.display = 'none'
|
||||
headerTitle.style.display = 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (
|
||||
currentPagePath === '/luscenje' ||
|
||||
currentPagePath === '/luscenje/id_luscenja/oss'
|
||||
) {
|
||||
const { offsetMain } = window.extractionElements
|
||||
offsetMain.addEventListener('click', handleClick)
|
||||
|
||||
function handleClick({ target }) {
|
||||
const editTask = target.closest('.edit-task')
|
||||
const deleteTask = target.closest('.delete-task')
|
||||
const doubleTask = target.closest('.double-task')
|
||||
if (editTask) {
|
||||
// alert('Greš na drug page...')
|
||||
} else if (deleteTask) {
|
||||
// deleteField(deleteTask)
|
||||
} else if (doubleTask) {
|
||||
duplicateTask(doubleTask)
|
||||
}
|
||||
}
|
||||
|
||||
function duplicateTask(ele) {
|
||||
const element = ele.closest('.task')
|
||||
const taskName = element.children[0].children[0].children[0].textContent
|
||||
const duplicateName = taskName + ' ' + 'copy'
|
||||
const taskCerif = element.children[0].children[0].children[1].textContent
|
||||
|
||||
// Create elements
|
||||
const taskNewContainer = document.createElement('div')
|
||||
const divSmFlex = document.createElement('div')
|
||||
const divSmGrid = document.createElement('div')
|
||||
const spanTaskName = document.createElement('span')
|
||||
const spanCerif = document.createElement('span')
|
||||
const divSmFlexAC = document.createElement('div')
|
||||
const btnStart = document.createElement('button')
|
||||
const btnImg = document.createElement('img')
|
||||
const btnSpan = document.createElement('span')
|
||||
const hr = document.createElement('hr')
|
||||
const divSmFlex2 = document.createElement('div')
|
||||
const divSmFlexACMb = document.createElement('div')
|
||||
const imgAlertCircle = document.createElement('img')
|
||||
const spanNew = document.createElement('span')
|
||||
const divSmFlexACMbMe = document.createElement('div')
|
||||
const divEditTask = document.createElement('div')
|
||||
const imgEditAlt = document.createElement('img')
|
||||
const spanEdit = document.createElement('span')
|
||||
const divDeleteTask = document.createElement('div')
|
||||
const imgDeleteAlt = document.createElement('img')
|
||||
const spanDelete = document.createElement('span')
|
||||
|
||||
taskNewContainer.className = 'container-fluid task task-new p-3 mb-4'
|
||||
divSmFlex.className = 'd-sm-flex justify-content-between'
|
||||
divSmGrid.className = 'd-sm-grid'
|
||||
|
||||
spanTaskName.className = 'bold-weight-black'
|
||||
spanTaskName.textContent = duplicateName
|
||||
|
||||
spanCerif.className = 'normal-gray mt-2 mb-2'
|
||||
spanCerif.textContent = taskCerif
|
||||
|
||||
divSmFlexAC.className = 'd-sm-flex align-items-center'
|
||||
btnStart.className = 'btn btn-secondary align-items-center d-flex'
|
||||
btnStart.type = 'button'
|
||||
btnImg.src = '/images/fi_arrow-right-circle.svg'
|
||||
btnSpan.className = 'ms-1'
|
||||
btnSpan.textContent = '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'
|
||||
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'
|
||||
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'
|
||||
|
||||
taskNewContainer.appendChild(divSmFlex)
|
||||
divSmFlex.appendChild(divSmGrid)
|
||||
divSmGrid.appendChild(spanTaskName)
|
||||
divSmGrid.appendChild(spanCerif)
|
||||
divSmFlex.appendChild(divSmFlexAC)
|
||||
divSmFlexAC.appendChild(btnStart)
|
||||
btnStart.appendChild(btnImg)
|
||||
btnStart.appendChild(btnSpan)
|
||||
taskNewContainer.appendChild(hr)
|
||||
taskNewContainer.appendChild(divSmFlex2)
|
||||
divSmFlex2.appendChild(divSmFlexACMb)
|
||||
divSmFlexACMb.appendChild(imgAlertCircle)
|
||||
divSmFlexACMb.appendChild(spanNew)
|
||||
divSmFlex2.appendChild(divSmFlexACMbMe)
|
||||
divSmFlexACMbMe.appendChild(divEditTask)
|
||||
divEditTask.appendChild(imgEditAlt)
|
||||
divEditTask.appendChild(spanEdit)
|
||||
divSmFlexACMbMe.appendChild(divDeleteTask)
|
||||
divDeleteTask.appendChild(imgDeleteAlt)
|
||||
divDeleteTask.appendChild(spanDelete)
|
||||
|
||||
const allTasksEl = document.getElementById('all-tasks')
|
||||
|
||||
allTasksEl.insertBefore(taskNewContainer, allTasksEl.firstChild)
|
||||
}
|
||||
}
|
||||
|
||||
// function deleteField(ele) {
|
||||
// const element = ele.closest('.task')
|
||||
// const modalUseBtn = document.getElementById('modal-use-btn')
|
||||
// modalUseBtn.addEventListener('click', () => {
|
||||
// element.remove()
|
||||
// })
|
||||
// element.remove()
|
||||
// }
|
||||
|
||||
adjustOffsetBy()
|
||||
}
|
||||
|
||||
function adjustOffsetBy() {
|
||||
const { offsetMain, fixedTopSection } = window.extractionElements
|
||||
const referenceHeight = fixedTopSection.offsetHeight
|
||||
const offsetHeader = document.getElementsByClassName('offset-header')
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
const headerPadding = document.getElementById('header-padding')
|
||||
|
||||
if (document.body.clientWidth < 1200) {
|
||||
if (offsetHeaderPadding !== null) offsetMain.style.paddingTop = `0px`
|
||||
} else {
|
||||
for (let i = 0; i < offsetHeader.length; i++) {
|
||||
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
if (headerPadding !== null) {
|
||||
const headerPaddingHeight = headerPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${headerPaddingHeight}px`
|
||||
}
|
||||
|
||||
if (offsetHeaderPadding !== null) {
|
||||
const offsetHeaderHeight = offsetHeaderPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${referenceHeight + offsetHeaderHeight}px`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mobileMoveContent() {
|
||||
const adminNavMobileEl = document.getElementById('admin-nav-mobile')
|
||||
const mobileRightHolder = document.getElementById('mobile-right-holder')
|
||||
const secondaryButton = document.querySelector('.header-btn-secondary')
|
||||
const primaryButton = document.querySelector('.header-btn')
|
||||
const siteHeading = document.getElementById('site-heading')
|
||||
const siteHeadingTextContent = siteHeading.textContent
|
||||
const navTitle = document.getElementById('nav-title')
|
||||
const headerContainerRight = document.querySelector(
|
||||
'.header-container-divider-right'
|
||||
)
|
||||
if (document.body.clientWidth <= 1200) {
|
||||
if (secondaryButton) {
|
||||
adminNavMobileEl.classList.add('align-items-center')
|
||||
adminNavMobileEl.classList.add('justify-content-between')
|
||||
mobileRightHolder.appendChild(secondaryButton)
|
||||
secondaryButton.style.height = '28px'
|
||||
secondaryButton.style.width = '99px'
|
||||
secondaryButton.style.marginRight = '10px'
|
||||
}
|
||||
if (primaryButton) {
|
||||
mobileRightHolder.appendChild(primaryButton)
|
||||
adminNavMobileEl.classList.add('align-items-center')
|
||||
adminNavMobileEl.classList.add('justify-content-between')
|
||||
primaryButton.style.height = '28px'
|
||||
primaryButton.style.width = '99px'
|
||||
primaryButton.style.marginRight = '10px'
|
||||
primaryButton.style.whiteSpace = 'nowrap'
|
||||
}
|
||||
navTitle.textContent = siteHeadingTextContent
|
||||
siteHeading.style.display = 'none'
|
||||
}
|
||||
if (document.body.clientWidth > 1200) {
|
||||
if (secondaryButton) {
|
||||
headerContainerRight.appendChild(secondaryButton)
|
||||
secondaryButton.style.height = ''
|
||||
secondaryButton.style.width = ''
|
||||
secondaryButton.style.marginRight = ''
|
||||
}
|
||||
if (primaryButton) {
|
||||
headerContainerRight.appendChild(primaryButton)
|
||||
adminNavMobileEl.classList.remove('align-items-center')
|
||||
adminNavMobileEl.classList.remove('justify-content-between')
|
||||
primaryButton.style.height = ''
|
||||
primaryButton.style.width = ''
|
||||
primaryButton.style.marginRight = ''
|
||||
primaryButton.style.whiteSpace = ''
|
||||
}
|
||||
|
||||
navTitle.textContent = 'Urejanje'
|
||||
siteHeading.style.display = 'block'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
const currentPagePath = location.pathname
|
||||
@@ -0,0 +1,81 @@
|
||||
/* global bootstrap */
|
||||
window.addEventListener('resize', () => {
|
||||
adjustOffsetBy()
|
||||
changeSubareasGroup()
|
||||
})
|
||||
adjustOffsetBy()
|
||||
|
||||
function adjustOffsetBy() {
|
||||
const fixedTopSection = document.getElementById('fixed-top-section')
|
||||
const offsetMain = document.getElementById('offset-main')
|
||||
const referenceHeight = fixedTopSection.offsetHeight
|
||||
const offsetHeader = document.getElementsByClassName('offset-header')
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
const headerPadding = document.getElementById('header-padding')
|
||||
|
||||
if (document.body.clientWidth < 1200) {
|
||||
if (offsetHeaderPadding !== null) offsetMain.style.paddingTop = `0px`
|
||||
} else {
|
||||
for (let i = 0; i < offsetHeader.length; i++) {
|
||||
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
if (headerPadding !== null) {
|
||||
const headerPaddingHeight = headerPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${headerPaddingHeight}px`
|
||||
}
|
||||
if (offsetHeaderPadding !== null) {
|
||||
const offsetHeaderHeight = offsetHeaderPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${referenceHeight + offsetHeaderHeight}px`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', () => changeSubareasGroup())
|
||||
window.addEventListener('load', () => changeSubareasGroup())
|
||||
|
||||
function changeSubareasGroup() {
|
||||
const subareaLinks = document.querySelectorAll('.subarea-link')
|
||||
subareaLinks.forEach(el => {
|
||||
const x = el.closest('.active')
|
||||
if (x !== null) {
|
||||
const sublinkSelected = x.closest('.help-links-subgroup')
|
||||
sublinkSelected.classList.add('active-subgroup')
|
||||
if (el.nextElementSibling !== null)
|
||||
el.nextSibling.style.maxHeight = 'fit-content'
|
||||
} else {
|
||||
if (el.nextElementSibling !== null) el.nextSibling.style.maxHeight = null
|
||||
if (el.parentElement.classList.contains('active-subgroup'))
|
||||
el.parentElement.classList.remove('active-subgroup')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const navigation = document.getElementById('help-nav-scrollspy')
|
||||
navigation.addEventListener('click', e => closeIfMobile(e))
|
||||
|
||||
function closeIfMobile(e) {
|
||||
const sideMenu = navigation.parentElement
|
||||
if (sideMenu.classList.contains('opened')) {
|
||||
if (e.target.tagName === 'A')
|
||||
// Call generic function for mobile menu closure from scripts.js
|
||||
toggleNav('slidable')
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const scrollSpy = new bootstrap.ScrollSpy(document.body, {
|
||||
target: '#help-nav-scrollspy',
|
||||
offset: 180
|
||||
})
|
||||
|
||||
const collapsibleElements = document.querySelectorAll('.help-collapsible')
|
||||
collapsibleElements.forEach(el =>
|
||||
el.addEventListener('click', () => {
|
||||
const elem = el.nextSibling
|
||||
if (elem.style.maxHeight && !el.classList.contains('active')) {
|
||||
elem.style.maxHeight = null
|
||||
} else {
|
||||
elem.style.maxHeight = 'fit-content'
|
||||
}
|
||||
})
|
||||
)
|
||||
@@ -0,0 +1,281 @@
|
||||
/* global axios, validator, removeJumpLogic */
|
||||
|
||||
/*
|
||||
|
||||
Design logic implementation
|
||||
Miha Stele, 2022
|
||||
|
||||
*/
|
||||
|
||||
// helper.js
|
||||
|
||||
const regBtn = document.querySelector('#regbtn')
|
||||
const logintBtn = document.querySelector('#loginbtn')
|
||||
const regForm = document.querySelector('#register-form')
|
||||
const loginForm = document.querySelector('#login-form')
|
||||
const regHeader = document.querySelector('.regtitle')
|
||||
const loginHeader = document.querySelector('.logintitle')
|
||||
const regDescription = document.querySelector('.regdesc')
|
||||
const loginDescription = document.querySelector('.logindesc')
|
||||
|
||||
const listenRegisterBtn = event => {
|
||||
logintBtn.className = logintBtn.className.replace('d-none', '')
|
||||
regBtn.className = regBtn.className + ' d-none'
|
||||
regForm.className = regForm.className.replace('d-none', '')
|
||||
loginForm.className = loginForm.className + ' d-none'
|
||||
regHeader.className = regHeader.className.replace('d-none', '')
|
||||
loginHeader.className = loginHeader.className + ' d-none'
|
||||
regDescription.className = regDescription.className.replace('d-none', '')
|
||||
loginDescription.className = loginDescription.className + ' d-none'
|
||||
}
|
||||
|
||||
const listenLoginBtn = event => {
|
||||
regBtn.className = regBtn.className.replace('d-none', '')
|
||||
logintBtn.className = logintBtn.className + ' d-none'
|
||||
loginForm.className = loginForm.className.replace('d-none', '')
|
||||
regForm.className = regForm.className + ' d-none'
|
||||
loginHeader.className = loginHeader.className.replace('d-none', '')
|
||||
regHeader.className = regHeader.className + ' d-none'
|
||||
loginDescription.className = loginDescription.className.replace('d-none', '')
|
||||
regDescription.className = regDescription.className + ' d-none'
|
||||
}
|
||||
|
||||
regBtn.addEventListener('click', listenRegisterBtn)
|
||||
logintBtn.addEventListener('click', listenLoginBtn)
|
||||
|
||||
/* validation */
|
||||
|
||||
// const loginErrorIconList = document.querySelector('.error-login-icon')
|
||||
|
||||
/* Note: Below 2 constant label arrays are in order */
|
||||
const registerErrorLabels = [
|
||||
'error-username',
|
||||
'error-name',
|
||||
'error-surname',
|
||||
'error-email',
|
||||
'error-password',
|
||||
'error-password-repeat'
|
||||
]
|
||||
|
||||
const registerInputLabels = [
|
||||
'register-username',
|
||||
'register-name',
|
||||
'register-surname',
|
||||
'register-email',
|
||||
'register-password',
|
||||
'register-password-repeat'
|
||||
]
|
||||
const registerErrorIndicatorpairs = {}
|
||||
|
||||
registerErrorLabels.forEach(errorLabel => {
|
||||
registerErrorIndicatorpairs[errorLabel] = []
|
||||
registerErrorIndicatorpairs[errorLabel].push(
|
||||
document.querySelector(`#${errorLabel}`)
|
||||
)
|
||||
registerErrorIndicatorpairs[errorLabel].push(
|
||||
document.querySelector(`.${errorLabel}`)
|
||||
)
|
||||
})
|
||||
|
||||
/*
|
||||
updateLoginRegisterErrorView
|
||||
|
||||
Shows and hides X icons and error labels of specific inputs in register error view
|
||||
|
||||
errorLabel - refrerence of the input label
|
||||
fail - determines if input is valid, if fail is equal to true, input is invalid
|
||||
input - id of the input, query selector is used in code. Should be a ref to <p> element
|
||||
description - optional description to add to the <p> error description
|
||||
|
||||
*/
|
||||
|
||||
function updateLoginRegisterErrorView(
|
||||
errorLabel,
|
||||
fail = true,
|
||||
description = ''
|
||||
) {
|
||||
if (fail) {
|
||||
registerErrorIndicatorpairs[errorLabel][0].style.visibility = 'visible' // <p>
|
||||
registerErrorIndicatorpairs[errorLabel][1].style.visibility = 'visible' // <img>
|
||||
} else {
|
||||
registerErrorIndicatorpairs[errorLabel][0].style.visibility = 'hidden'
|
||||
registerErrorIndicatorpairs[errorLabel][1].style.visibility = 'hidden'
|
||||
}
|
||||
if (description.length > 0) {
|
||||
registerErrorIndicatorpairs[errorLabel][0].textContent = description
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Show error message from the label that represents the error returned from the server
|
||||
Includes error X icons for login
|
||||
*/
|
||||
function showErrorReturnedFromServer(
|
||||
errorLabel,
|
||||
exception,
|
||||
description = '',
|
||||
isLogin = false
|
||||
) {
|
||||
const elt = document.getElementById(errorLabel)
|
||||
if (exception) {
|
||||
if (description.length > 0) {
|
||||
elt.textContent = description
|
||||
}
|
||||
elt.style.visibility = 'visible'
|
||||
if (isLogin) {
|
||||
document.querySelectorAll('.error-login-icon').forEach(e => {
|
||||
e.style.visibility = 'visible'
|
||||
})
|
||||
}
|
||||
} else {
|
||||
elt.style.visibility = 'hidden'
|
||||
if (isLogin) {
|
||||
document.querySelectorAll('.error-login-icon').forEach(e => {
|
||||
e.style.visibility = 'hidden'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateRegisterWindowOnSuccess(
|
||||
modalBodyIdRef,
|
||||
modalFooterIdRef,
|
||||
name,
|
||||
surname,
|
||||
days = 7
|
||||
) {
|
||||
const body = document.getElementById(modalBodyIdRef)
|
||||
const footer = document.getElementById(modalFooterIdRef)
|
||||
|
||||
body.removeChild(document.querySelector('.pspelogsig-5'))
|
||||
footer.removeChild(footer.firstElementChild)
|
||||
footer.appendChild(document.createElement('button'))
|
||||
const btn = footer.firstElementChild
|
||||
btn.classList = 'btn btn-secondary text-secondary'
|
||||
btn.textContent = '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.`
|
||||
}
|
||||
|
||||
// login and register
|
||||
|
||||
{
|
||||
const loginForm = document.getElementById('login-form')
|
||||
loginForm.messageBind = document.getElementById('error-description')
|
||||
const registerForm = document.getElementById('register-form')
|
||||
registerForm.messageBind = document.getElementById(
|
||||
'register-message-container'
|
||||
)
|
||||
// const messageContainer = document.getElementById('message-container')
|
||||
|
||||
loginForm.addEventListener('submit', submitForm)
|
||||
registerForm.addEventListener('submit', submitForm)
|
||||
|
||||
// TODO Function name is very general. Make sure it doesn't conflict, override or
|
||||
// TODO get overriden by any other function later and rename or generalize as needed.
|
||||
async function submitForm(event) {
|
||||
event.preventDefault()
|
||||
const payload = Object.fromEntries(new FormData(event.target))
|
||||
const isRegister = event.target.action.includes('/register')
|
||||
let failFrontendValidation = false
|
||||
|
||||
// console.log(payload)
|
||||
|
||||
try {
|
||||
if (isRegister) {
|
||||
// validation empty inputs for register
|
||||
const inputs = []
|
||||
let iterator = 0
|
||||
registerInputLabels.forEach(label => {
|
||||
const curr = document.querySelector(`#${label}`)
|
||||
inputs.push(curr)
|
||||
|
||||
if (curr.value.length < 1) {
|
||||
updateLoginRegisterErrorView(
|
||||
registerErrorLabels[iterator],
|
||||
true,
|
||||
'Prazno obvezno polje'
|
||||
)
|
||||
failFrontendValidation = true
|
||||
} else {
|
||||
updateLoginRegisterErrorView(registerErrorLabels[iterator], false)
|
||||
}
|
||||
iterator++
|
||||
})
|
||||
// end validation for empty inputs in register
|
||||
|
||||
// other register validators
|
||||
if (!validator.isEmail(payload.email)) {
|
||||
failFrontendValidation = true
|
||||
updateLoginRegisterErrorView(
|
||||
'error-email',
|
||||
true,
|
||||
'Neveljavna e-pošta'
|
||||
)
|
||||
} else {
|
||||
updateLoginRegisterErrorView('error-email', false)
|
||||
}
|
||||
|
||||
if (!validator.isLength(payload.password, { min: 8 })) {
|
||||
failFrontendValidation = true
|
||||
updateLoginRegisterErrorView(
|
||||
'error-password',
|
||||
true,
|
||||
'Geslo je prekratko'
|
||||
)
|
||||
} else {
|
||||
updateLoginRegisterErrorView('error-password', false)
|
||||
}
|
||||
|
||||
if (!validator.equals(payload.password, payload.passwordRepeat)) {
|
||||
failFrontendValidation = true
|
||||
updateLoginRegisterErrorView(
|
||||
'error-password-repeat',
|
||||
true,
|
||||
'Geslo se ne ujema'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (!failFrontendValidation) {
|
||||
const { data } = await axios.post(event.target.action, payload)
|
||||
|
||||
console.log(data)
|
||||
|
||||
// TODO HANDLE TRUE OR FALSE USERNAME BELOW
|
||||
|
||||
if (isRegister) {
|
||||
updateRegisterWindowOnSuccess(
|
||||
'logreg-mb',
|
||||
'logreg-mf',
|
||||
payload.firstName,
|
||||
payload.lastName
|
||||
)
|
||||
} else {
|
||||
window.location.href = '/'
|
||||
}
|
||||
}
|
||||
|
||||
// event.target.messageBind.textContent = data
|
||||
} catch (error) {
|
||||
let message = 'Prišlo je do napake.'
|
||||
if (error.response) {
|
||||
message = error.response.data
|
||||
} else if (error.request) {
|
||||
message = 'Strežnik ni dosegljiv. Poskusite kasneje.'
|
||||
}
|
||||
|
||||
showErrorReturnedFromServer(
|
||||
event.target.messageBind.id,
|
||||
true,
|
||||
message,
|
||||
!isRegister
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/* global $, refreshLabels, setVisibleSuggestionsRoot, closeUtilityContainers, sfm,
|
||||
inputs */
|
||||
|
||||
const dcw = document.documentElement.clientWidth
|
||||
const SMALLER_THAN_MDEIUM_SCREEN = () => {
|
||||
const dynamicDcw = document.documentElement.clientWidth
|
||||
return dynamicDcw < 768
|
||||
}
|
||||
|
||||
const searchFilterDOM = {
|
||||
pd: $('.select-domain-field'), // legacy word used for domain
|
||||
sl: $('.select-src-lang-field'),
|
||||
tl: $('.select-dest-lang-field'),
|
||||
d: $('.select-dict-field'),
|
||||
s: $('.select-source-field')
|
||||
}
|
||||
|
||||
// Get the input field
|
||||
// click on enter and focused on enter classes are not used anymore
|
||||
const buttonMainSearch = document.querySelector('#search-button-main')
|
||||
const inputMainSearch = document.querySelector('#search-query')
|
||||
|
||||
// Execute a function when the user presses a key on the keyboard
|
||||
if (buttonMainSearch && inputMainSearch) {
|
||||
inputMainSearch.addEventListener('keypress', function (event) {
|
||||
// If the user presses the "Enter" key on the keyboard
|
||||
if (event.key === 'Enter') {
|
||||
// Cancel the default action, if needed
|
||||
event.preventDefault()
|
||||
// Trigger the button element with a click
|
||||
buttonMainSearch.click()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Secondary searchbar search logic (for asmall search screens)
|
||||
// A lot of DUPLICATE code, enhance later
|
||||
|
||||
// search implementation functions
|
||||
|
||||
// Also used in search field
|
||||
// function calibrateWithDelay() {
|
||||
// setTimeout(() => {
|
||||
// moveContainer(rootClass, boundingBoxRect)
|
||||
// updatePopupDimensions(rootCont, boundingBox)
|
||||
// }, 20)
|
||||
// }
|
||||
|
||||
function bindKeys(bindTo) {
|
||||
const bindToElement = document.querySelector(bindTo)
|
||||
document.querySelectorAll('.kbd-key').forEach(e => {
|
||||
e.addEventListener('click', function (e) {
|
||||
const oldFocusIndex = bindToElement.selectionStart
|
||||
bindToElement.value = `${bindToElement.value.substring(
|
||||
0,
|
||||
bindToElement.selectionStart
|
||||
)}${e.target.textContent}${bindToElement.value.substring(
|
||||
bindToElement.selectionEnd
|
||||
)}`
|
||||
bindToElement.focus()
|
||||
bindToElement.selectionStart = oldFocusIndex + 1
|
||||
bindToElement.selectionEnd = oldFocusIndex + 1
|
||||
|
||||
// setTimeout(() => {
|
||||
// // calibrateWithDelay()
|
||||
// renderSuggestionsVK(bindToElement.value)
|
||||
// }, 10)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const listenForTyping = function (event) {
|
||||
// moveContainer(rootClass, boundingBox)
|
||||
// updatePopupDimensions(rootCont, boundingBox)
|
||||
if (event.code === 'Enter') {
|
||||
event.preventDefault()
|
||||
closeUtilityContainers()
|
||||
}
|
||||
|
||||
/* ************************* suggestions code below ************************* */
|
||||
// if (init) {
|
||||
// removeSuggestions(root, childOfRootId)
|
||||
// } else {
|
||||
// init = true
|
||||
// }
|
||||
|
||||
// renderSuggestions(
|
||||
// suggestions.filter(f => {
|
||||
// /* if (event.target.value.length === 1) {
|
||||
// return f[0] === event.target.value
|
||||
// } */
|
||||
|
||||
// return (
|
||||
// f.substring(0, event.target.value.length).toLowerCase() ===
|
||||
// event.target.value.toLowerCase()
|
||||
// )
|
||||
// }),
|
||||
// root,
|
||||
// boundingBox,
|
||||
// 'suggestions-root'
|
||||
// ) // .filter(event.target), rect, rt)
|
||||
// setVisibleSuggestionsRoot(true)
|
||||
|
||||
// Below code is just calibration of the popup windows
|
||||
// calibrateWithDelay()
|
||||
}
|
||||
|
||||
const inputQueryMain = document.getElementById('search-query')
|
||||
const inputQuerySecondary = document.getElementById('search-query-sec')
|
||||
|
||||
if (inputQueryMain) {
|
||||
inputQueryMain.addEventListener('keyup', listenForTyping)
|
||||
}
|
||||
|
||||
if (inputQuerySecondary) {
|
||||
inputQuerySecondary.addEventListener('keyup', listenForTyping)
|
||||
}
|
||||
|
||||
/*
|
||||
searchQuery
|
||||
- searchString - search string provided in the search input
|
||||
- REMOVED: queryParams - parameters such as filters, etc. "q" is not allowed as query param since search string reserves the q parameter
|
||||
- searchFilterDOM - jQuery DOM elements due to variable reusability. There will be converted to querparams
|
||||
|
||||
*/
|
||||
function searchQuery(searchString, searchFilterDOM = {}) {
|
||||
const stringBuilder = `/iskanje?q=${searchString}`
|
||||
|
||||
const url = new URL(stringBuilder, location.protocol + '//' + location.host)
|
||||
|
||||
// Map filter DOM elements to query parameters
|
||||
Object.entries(searchFilterDOM).forEach(([k, v]) => {
|
||||
/* queryParams[k] = v.val().reduce((acc, el, index) => {
|
||||
if(index == 0)
|
||||
}) */
|
||||
|
||||
if (v) {
|
||||
v.val().forEach(val => {
|
||||
url.searchParams.append(k, val)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
/*
|
||||
// Todo - map query names if required
|
||||
Object.keys(queryParams).forEach(key => {
|
||||
if (key !== 'q') {
|
||||
// stringBuilder = `${stringBuilder}&${key}=${queryParams[key]}`
|
||||
url.searchParams.append(key, queryParams[key])
|
||||
}
|
||||
})
|
||||
*/
|
||||
|
||||
document.location.href = url
|
||||
}
|
||||
|
||||
// end search implementation functions
|
||||
|
||||
// search filter functions
|
||||
function sbmFn(sbm) {
|
||||
if (sbm) {
|
||||
sbm.addEventListener('click', e => {
|
||||
let inputString
|
||||
if (inputQuerySecondary && SMALLER_THAN_MDEIUM_SCREEN()) {
|
||||
inputString = inputQuerySecondary.value
|
||||
} else {
|
||||
inputString = inputQueryMain.value
|
||||
}
|
||||
|
||||
// TODO fill query parameters below for the core search example: domain, dictionary, ...
|
||||
|
||||
if (inputString === '') {
|
||||
inputString = '*'
|
||||
}
|
||||
|
||||
searchQuery(inputString, searchFilterDOM)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
function handleSSCLocation() {
|
||||
/*
|
||||
function removeSSCChild(elt) {
|
||||
if (elt) {
|
||||
elt.innerHMTL = ''
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function swapContainer(cnt, rmCnt, elt) {
|
||||
if (cnt) {
|
||||
cnt.appendChild(elt)
|
||||
}
|
||||
// removeSSCChild(rmCnt)
|
||||
}
|
||||
|
||||
const SSCSmallContainerHolder = document.getElementById('SSCSec')
|
||||
const SSCContainerHolder = document.getElementById('SSC')
|
||||
const SSCContainer = document.querySelector('.search-suggestion-container')
|
||||
|
||||
if (SMALLER_THAN_MDEIUM_SCREEN()) {
|
||||
swapContainer(SSCSmallContainerHolder, SSCContainerHolder, SSCContainer)
|
||||
} else {
|
||||
swapContainer(SSCContainerHolder, SSCSmallContainerHolder, SSCContainer)
|
||||
}
|
||||
}
|
||||
|
||||
const focusOnCompletePromptForSmallDevices = () => {
|
||||
focusOnCompletePromtBase(inputQuerySecondary)
|
||||
}
|
||||
|
||||
const focusOnCompletePrompt = () => {
|
||||
focusOnCompletePromtBase(inputQueryMain)
|
||||
}
|
||||
|
||||
const focusOnCompletePromtBase = queryInput => {
|
||||
queryInput.focus()
|
||||
queryInput.select()
|
||||
}
|
||||
|
||||
// Get the input field
|
||||
const buttonOnSmallScreen = document.querySelector('#search-button-main-sec')
|
||||
|
||||
// Execute a function when the user presses a key on the keyboard
|
||||
if (buttonOnSmallScreen && inputQuerySecondary) {
|
||||
inputQuerySecondary.addEventListener('keypress', function (event) {
|
||||
// If the user presses the "Enter" key on the keyboard
|
||||
if (event.key === 'Enter') {
|
||||
// Cancel the default action, if needed
|
||||
event.preventDefault()
|
||||
// Trigger the buttonOnSmallScreen element with a click
|
||||
buttonOnSmallScreen.click()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function submitForSSCButtons(btnQuery, isOnce = true) {
|
||||
sbmFn(document.querySelector(btnQuery))
|
||||
if (document.querySelector(btnQuery) && isOnce) {
|
||||
sbmFn(document.querySelector('.search-btn-a'))
|
||||
}
|
||||
}
|
||||
|
||||
submitForSSCButtons('#search-button-main')
|
||||
submitForSSCButtons('#search-button-main-sec', false)
|
||||
|
||||
/*
|
||||
sbmFn(document.querySelector('#search-button-main'))
|
||||
if (document.querySelector('#search-button-main')) {
|
||||
sbmFn(document.querySelector('.search-btn-a'))
|
||||
} */
|
||||
|
||||
if (inputQueryMain) {
|
||||
bindKeys('#search-query')
|
||||
}
|
||||
|
||||
if (inputQuerySecondary) {
|
||||
bindKeys('#search-query-sec')
|
||||
}
|
||||
|
||||
document.querySelector('.clear-f')?.addEventListener('click', e => {
|
||||
if (inputQueryMain) {
|
||||
inputQueryMain.value = ''
|
||||
}
|
||||
|
||||
if (inputQuerySecondary) {
|
||||
inputQuerySecondary.value = ''
|
||||
}
|
||||
|
||||
Object.values(searchFilterDOM).forEach(element => {
|
||||
if (element) {
|
||||
element.val(null).trigger('change')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
document.addEventListener('click', event => {
|
||||
try {
|
||||
refreshLabels(inputs)
|
||||
|
||||
const specificSQMQuery = document.querySelector(
|
||||
'#search-query.search-input'
|
||||
)
|
||||
// console.log(event)
|
||||
if (event.target.classList[1].slice(-5) === '-sugg') {
|
||||
specificSQMQuery.value = event.target.textContent
|
||||
}
|
||||
|
||||
// updatePopupDimensions(rootCont, boundingBox)
|
||||
} catch (e) {
|
||||
// console.log(e)
|
||||
// console.log(e)
|
||||
}
|
||||
setVisibleSuggestionsRoot(false)
|
||||
|
||||
// Below code is just calibration of the popup windows
|
||||
// moveContainer(rootClass, boundingBoxRect)
|
||||
// updatePopupDimensions(rootCont, boundingBox)
|
||||
})
|
||||
|
||||
if (sfm) {
|
||||
sfm.addEventListener('click', focusOnCompletePrompt)
|
||||
sfm.addEventListener('click', () => {
|
||||
if (SMALLER_THAN_MDEIUM_SCREEN()) {
|
||||
focusOnCompletePromptForSmallDevices()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// inital focus on searchbars script closure
|
||||
// focus on login/register
|
||||
|
||||
if (inputQueryMain) {
|
||||
focusOnCompletePrompt()
|
||||
if (SMALLER_THAN_MDEIUM_SCREEN()) {
|
||||
focusOnCompletePromptForSmallDevices()
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
handleSSCLocation()
|
||||
})
|
||||
|
||||
$(document).ready(function () {
|
||||
handleSSCLocation()
|
||||
})
|
||||
@@ -0,0 +1,103 @@
|
||||
const allMixedContentFields = document.querySelectorAll('.mc-field')
|
||||
|
||||
allMixedContentFields.forEach(el =>
|
||||
el.addEventListener('focusin', () => 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()
|
||||
}
|
||||
})
|
||||
|
||||
function showMCButtons(element) {
|
||||
const parent = element.parentElement.parentElement.parentElement
|
||||
const btnGrp = parent.querySelector('.mc-buttons-group')
|
||||
btnGrp.classList.remove('d-none')
|
||||
const btnGrpChildren = btnGrp.children
|
||||
const childrenBtns = Array.from(btnGrpChildren)
|
||||
childrenBtns.forEach(el =>
|
||||
el.addEventListener(
|
||||
'click',
|
||||
() => {
|
||||
addMixedContentInput(el, element)
|
||||
},
|
||||
// TODO Possibly a dirty hack. Look into it at a later time.
|
||||
{ once: true }
|
||||
)
|
||||
)
|
||||
document.addEventListener('click', function (event) {
|
||||
if (parent !== event.target && !parent.contains(event.target)) {
|
||||
btnGrp.classList.add('d-none')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function addMixedContentInput(el, selectedEl) {
|
||||
const inputText = selectedEl.value
|
||||
const selectedStart = selectedEl.selectionStart
|
||||
const selectedEnd = selectedEl.selectionEnd
|
||||
const selectedText = inputText.slice(
|
||||
selectedEl.selectionStart,
|
||||
selectedEl.selectionEnd
|
||||
)
|
||||
|
||||
if (el.classList.contains('mc-bold') && selectedText.length) {
|
||||
selectedEl.value =
|
||||
inputText.substring(0, selectedStart) +
|
||||
'<b>' +
|
||||
inputText.substring(selectedStart, selectedEnd) +
|
||||
'</b> ' +
|
||||
inputText.substring(selectedEnd)
|
||||
}
|
||||
|
||||
if (el.classList.contains('mc-italic') && selectedText.length) {
|
||||
selectedEl.value =
|
||||
inputText.substring(0, selectedStart) +
|
||||
'<i>' +
|
||||
inputText.substring(selectedStart, selectedEnd) +
|
||||
'</i> ' +
|
||||
inputText.substring(selectedEnd)
|
||||
}
|
||||
|
||||
if (el.classList.contains('mc-supscript') && selectedText.length) {
|
||||
selectedEl.value =
|
||||
inputText.substring(0, selectedStart) +
|
||||
'<sup>' +
|
||||
inputText.substring(selectedStart, selectedEnd) +
|
||||
'</sup> ' +
|
||||
inputText.substring(selectedEnd)
|
||||
}
|
||||
|
||||
if (el.classList.contains('mc-subscript') && selectedText.length) {
|
||||
selectedEl.value =
|
||||
inputText.substring(0, selectedStart) +
|
||||
'<sub>' +
|
||||
inputText.substring(selectedStart, selectedEnd) +
|
||||
'</sub> ' +
|
||||
inputText.substring(selectedEnd)
|
||||
}
|
||||
|
||||
if (el.classList.contains('mc-hyperlink') && selectedText.length) {
|
||||
selectedEl.value =
|
||||
inputText.substring(0, selectedStart) +
|
||||
'<link url="">' +
|
||||
inputText.substring(selectedStart, selectedEnd) +
|
||||
'</link> ' +
|
||||
inputText.substring(selectedEnd)
|
||||
}
|
||||
|
||||
if (el.classList.contains('mc-line-break')) {
|
||||
selectedEl.value =
|
||||
inputText.substring(0, selectedStart) +
|
||||
'<br />' +
|
||||
inputText.substring(selectedEnd)
|
||||
el.removeEventListener('click', () => addMixedContentInput, false)
|
||||
}
|
||||
|
||||
// selectedEl.focus()
|
||||
// selectedEl.setSelectionRange(selectedStart, selectedEnd)
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/* global axios */
|
||||
|
||||
/* async function getDataForPageWithQueryForArrayByID(
|
||||
page,
|
||||
searchQuery,
|
||||
filters = {}
|
||||
) {
|
||||
const qParams = new URL(location).searchParams
|
||||
qParams.set('p', page)
|
||||
qParams.set('q', searchQuery)
|
||||
|
||||
// console.log(filters)
|
||||
Object.entries(filters).forEach(([k, v]) => {
|
||||
// console.log(`k=${k}`)
|
||||
// console.log(`v=${v}`)
|
||||
v.forEach(element => {
|
||||
if (qParams.has(k)) {
|
||||
qParams.append(k, element.id)
|
||||
} else {
|
||||
qParams.set(k, element.id)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const url = `/api/v1/search/dictionaries?${qParams}`
|
||||
|
||||
return await axios.get(url)
|
||||
} */
|
||||
|
||||
function prepareQueryArrayForArrayWithIDs(page, searchQuery, filters = {}) {
|
||||
const qParams = new URL(location).searchParams
|
||||
qParams.set('p', page)
|
||||
qParams.set('q', searchQuery)
|
||||
|
||||
// console.log(filters)
|
||||
Object.entries(filters).forEach(([k, v]) => {
|
||||
// console.log(`k=${k}`)
|
||||
// console.log(`v=${v}`)
|
||||
v.forEach(element => {
|
||||
if (qParams.has(k)) {
|
||||
qParams.append(k, element.id)
|
||||
} else {
|
||||
qParams.set(k, element.id)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return qParams
|
||||
}
|
||||
|
||||
async function prepareQueryParamsBasic(queryParams, URLSearchParams = false) {
|
||||
let qParams
|
||||
if (URLSearchParams) {
|
||||
qParams = URLSearchParams
|
||||
} else {
|
||||
qParams = new URL(location).searchParams
|
||||
}
|
||||
|
||||
Object.entries(queryParams).forEach(([k, v]) => {
|
||||
qParams.set(k, v)
|
||||
})
|
||||
const url = `/api/v1/search/dictionaries?${qParams}`
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
async function getDataForPageWithQueryForArray(
|
||||
page,
|
||||
searchQuery,
|
||||
filters = {}
|
||||
) {
|
||||
const qParams = new URL(location).searchParams
|
||||
qParams.set('p', page)
|
||||
qParams.set('q', searchQuery)
|
||||
|
||||
// console.log(filters)
|
||||
Object.entries(filters).forEach(([k, v]) => {
|
||||
// console.log(`k=${k}`)
|
||||
// console.log(`v=${v}`)
|
||||
v.forEach(element => {
|
||||
if (qParams.has(k)) {
|
||||
qParams.append(k, element)
|
||||
} else {
|
||||
qParams.set(k, element)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const url = `/api/v1/search/dictionaries?${qParams}`
|
||||
|
||||
return await axios.get(url)
|
||||
}
|
||||
|
||||
async function getDataForQueryParams(queryParams) {
|
||||
const qParams = new URL(location).searchParams
|
||||
|
||||
Object.entries(queryParams).forEach(([k, v]) => {
|
||||
qParams.set(k, v)
|
||||
})
|
||||
const url = `/api/v1/search/dictionaries?${qParams}`
|
||||
|
||||
return await axios.get(url)
|
||||
}
|
||||
|
||||
// NEW METHODS, REFACTOR TO BOTTOM
|
||||
|
||||
function prepareQueryParams(queryParams, filters = {}) {
|
||||
const qParams = new URL(location).searchParams
|
||||
|
||||
Object.entries(filters).forEach(([k, v]) => {
|
||||
// console.log(`k=${k}`)
|
||||
// console.log(`v=${v}`)
|
||||
v.forEach(element => {
|
||||
if (qParams.has(k)) {
|
||||
qParams.append(k, element.id)
|
||||
} else {
|
||||
qParams.set(k, element.id)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Object.entries(queryParams).forEach(([k, v]) => {
|
||||
qParams.set(k, v)
|
||||
})
|
||||
|
||||
return qParams
|
||||
}
|
||||
|
||||
async function getDataFromURLSearchParams(URLSearchParams) {
|
||||
const url = `/api/v1/search/dictionaries?${URLSearchParams}`
|
||||
|
||||
return await axios.get(url)
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
// const currentPagePath = location.pathname
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
init()
|
||||
})
|
||||
|
||||
function init() {
|
||||
const ce = {}
|
||||
window.resultElements = ce
|
||||
|
||||
ce.textDescription = document.getElementById('text-description')
|
||||
ce.headerTitle = document.getElementById('site-header-title')
|
||||
ce.fixedTopSection = document.getElementById('fixed-top-section')
|
||||
ce.offsetMain = document.getElementById('offset-main')
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
adjustOffsetBy()
|
||||
hideAndShowHeader()
|
||||
})
|
||||
window.onscroll = hideAndShowHeader
|
||||
|
||||
function hideAndShowHeader() {
|
||||
const { textDescription, headerTitle } = window.resultElements
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
|
||||
if (document.body.clientWidth > 1200) {
|
||||
if (document.documentElement.scrollTop < 50) {
|
||||
textDescription.style.display = 'block'
|
||||
headerTitle.style.display = 'block'
|
||||
if (offsetHeaderPadding !== null)
|
||||
offsetHeaderPadding.className = 'header-section-root pb-0'
|
||||
} else {
|
||||
textDescription.style.display = 'none'
|
||||
headerTitle.style.display = 'none'
|
||||
if (offsetHeaderPadding !== null)
|
||||
offsetHeaderPadding.className =
|
||||
'header-section-root offset-padding pb-0'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adjustOffsetBy()
|
||||
}
|
||||
|
||||
function adjustOffsetBy() {
|
||||
const { offsetMain, fixedTopSection } = window.resultElements
|
||||
const referenceHeight = fixedTopSection.offsetHeight
|
||||
const offsetHeader = document.getElementsByClassName('offset-header')
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
const adminNavMobile = document.getElementsByClassName('admin-nav')
|
||||
const headerPadding = document.getElementById('header-padding')
|
||||
const keyboard = document.getElementsByClassName('kbd')[0]
|
||||
|
||||
const width = document.body.offsetWidth
|
||||
|
||||
let offsetKbdConstant = 21
|
||||
if (width > 1500) {
|
||||
offsetKbdConstant = 20
|
||||
} else if (width < 837) {
|
||||
if (width > 766) {
|
||||
/* todo */
|
||||
offsetKbdConstant = 10
|
||||
keyboard.style.width = keyboard.style.width * 0.7
|
||||
}
|
||||
}
|
||||
|
||||
const kbdoffset = width / 2 - keyboard.offsetWidth / 2 - offsetKbdConstant
|
||||
|
||||
if (width < 767) {
|
||||
keyboard.style.left = 0
|
||||
keyboard.style.top = '125px'
|
||||
keyboard.style.width = '100%'
|
||||
} else {
|
||||
keyboard.style.left = `${kbdoffset}px`
|
||||
}
|
||||
|
||||
keyboard.style.height = 'auto'
|
||||
|
||||
if (document.body.clientWidth < 1200) {
|
||||
for (let i = 0; i < adminNavMobile.length; i++) {
|
||||
adminNavMobile[i].style.paddingTop = `${referenceHeight}px`
|
||||
// offsetHeaderPadding.style.padding = '40px'
|
||||
// offsetMain.style.paddingTop = `${referenceHeight + 40}px`
|
||||
}
|
||||
if (offsetHeaderPadding !== null)
|
||||
offsetHeaderPadding.style.paddingTop = '20px'
|
||||
|
||||
if (headerPadding !== null) headerPadding.style.paddingTop = '60px'
|
||||
offsetMain.style.paddingTop = `0px`
|
||||
} else {
|
||||
for (let i = 0; i < offsetHeader.length; i++) {
|
||||
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
if (headerPadding !== null) headerPadding.style.paddingTop = '60px'
|
||||
offsetMain.style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,263 @@
|
||||
/* global $, axios, initPagination, removeAllChildNodes, closeUtilityContainers, prepareQueryArrayForArrayWithIDs, getDataFromURLSearchParams, prepareQueryParams, focusOnCompletePrompt */
|
||||
|
||||
{
|
||||
/*
|
||||
$('tr').click(function (e) {
|
||||
// console.log(e)
|
||||
|
||||
const id = e.currentTarget.id
|
||||
|
||||
if (e.currentTarget.id) {
|
||||
window.location.href = `/slovarji/${id}/o-slovarju?sentFromEntryId=dictsList`
|
||||
}
|
||||
})
|
||||
|
||||
$('tr').hover(e => $('i', e.target).toggleClass('outline'))
|
||||
*/
|
||||
|
||||
let orderType = 'dictName'
|
||||
let orderIndex = false // false - ASC, true - DESC
|
||||
let currentPage = 1
|
||||
let primaryDomains = []
|
||||
let qFilter = ''
|
||||
|
||||
document
|
||||
.getElementById('dictionaries-search-form')
|
||||
.addEventListener('submit', e => {
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
const submitFilter = async e => {
|
||||
const search = document.getElementById('search-query').value
|
||||
const domainFilter = {}
|
||||
|
||||
const pd = $('#domain-select').select2('data')
|
||||
|
||||
pd.forEach(el => {
|
||||
if (domainFilter.pd) {
|
||||
domainFilter.pd.push(el.id)
|
||||
} else {
|
||||
domainFilter.pd = [el.id]
|
||||
}
|
||||
})
|
||||
|
||||
if (pd) {
|
||||
domainFilter.pd = pd // Array of primary domain filter, ex. ['2', '234, '310']
|
||||
}
|
||||
|
||||
primaryDomains = pd
|
||||
qFilter = search
|
||||
|
||||
const preparedQuery = prepareQueryArrayForArrayWithIDs(
|
||||
1,
|
||||
search,
|
||||
domainFilter
|
||||
)
|
||||
const res = await getDataFromURLSearchParams(preparedQuery)
|
||||
|
||||
const page = +res.headers.page
|
||||
currentPage = page
|
||||
const numberOfAllPages = +res.headers['number-of-all-pages']
|
||||
// const resultsMarkup = res.data
|
||||
|
||||
removeAllChildNodes(resultsListEl)
|
||||
// renderResults(resultsMarkup)
|
||||
updatePager(page, numberOfAllPages)
|
||||
|
||||
renderResults(res.data)
|
||||
|
||||
addListenersOnRefresh()
|
||||
}
|
||||
|
||||
document
|
||||
.querySelector('#search-in-filter-modal')
|
||||
.addEventListener('click', submitFilter)
|
||||
|
||||
const dsb = document.querySelector('#dicts-search-btn')
|
||||
|
||||
dsb.addEventListener('click', submitFilter)
|
||||
dsb.addEventListener('click', focusOnCompletePrompt)
|
||||
dsb.addEventListener('click', closeUtilityContainers)
|
||||
|
||||
const resultsListEl = document.querySelector('.table-dict-list')
|
||||
const initialPage = +new URL(location).searchParams.get('p') || 1
|
||||
|
||||
const updatePager = initPagination('pagination', onPageChange, initialPage)
|
||||
resultsListEl.addEventListener('click', onResultClick)
|
||||
|
||||
async function onPageChange(newPage) {
|
||||
const receivedPageNumber = await changePage(newPage)
|
||||
updateUrlAndHistory(receivedPageNumber)
|
||||
}
|
||||
|
||||
async function changePage(newPage) {
|
||||
try {
|
||||
const qparams = prepareQueryParams(
|
||||
{
|
||||
p: newPage,
|
||||
orderType,
|
||||
orderIndex,
|
||||
q: qFilter
|
||||
},
|
||||
{ pd: primaryDomains }
|
||||
)
|
||||
const res = await getDataFromURLSearchParams(qparams)
|
||||
|
||||
const page = +res.headers.page
|
||||
currentPage = page
|
||||
const numberOfAllPages = +res.headers['number-of-all-pages']
|
||||
const resultsMarkup = res.data
|
||||
|
||||
removeAllChildNodes(resultsListEl)
|
||||
renderResults(resultsMarkup)
|
||||
updatePager(page, numberOfAllPages)
|
||||
|
||||
// important
|
||||
addListenersOnRefresh()
|
||||
|
||||
return page
|
||||
} 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()
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: think of a way to reduce redundancy of the functions below */
|
||||
|
||||
async function getDataForPage(page) {
|
||||
const qParams = new URL(location).searchParams
|
||||
qParams.set('p', page)
|
||||
const url = `/api/v1/search/dictionaries?${qParams}`
|
||||
|
||||
return await axios.get(url)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
getDataForPageWithQuery
|
||||
|
||||
inputs:
|
||||
- page: elements displayed in the page specified
|
||||
- searchQuery: search string
|
||||
- filters: filter elements o be added,
|
||||
format must be as following
|
||||
{
|
||||
FILTER_NAME_1: [FILTER_1, FILTER_2, ..., FILTER_N],
|
||||
FILTER_NAME_2: [...]
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
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)
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
// order type -> what to order
|
||||
// order index -> 0 - none, 1 - ASC, 2 - DESC
|
||||
async function sortQuery(orderType, orderIndex) {
|
||||
const queryParams = prepareQueryParams(
|
||||
{
|
||||
p: currentPage,
|
||||
orderType,
|
||||
orderIndex,
|
||||
q: qFilter
|
||||
},
|
||||
{ pd: primaryDomains }
|
||||
)
|
||||
|
||||
/// copied code, OPTIMIZE
|
||||
const res = await getDataFromURLSearchParams(queryParams)
|
||||
|
||||
const page = +res.headers.page
|
||||
const numberOfAllPages = +res.headers['number-of-all-pages']
|
||||
// const resultsMarkup = res.data
|
||||
|
||||
removeAllChildNodes(resultsListEl)
|
||||
// renderResults(resultsMarkup)
|
||||
updatePager(page, numberOfAllPages)
|
||||
|
||||
renderResults(res.data)
|
||||
}
|
||||
|
||||
// non-pure fn
|
||||
async function sortPlaceholder(name) {
|
||||
if (orderType === name) {
|
||||
orderIndex = !orderIndex
|
||||
} else {
|
||||
orderType = name
|
||||
orderIndex = false
|
||||
}
|
||||
|
||||
// reset on begin
|
||||
|
||||
await sortQuery(orderType, orderIndex)
|
||||
|
||||
addListenersOnRefresh()
|
||||
|
||||
// Ordering of code required because we apply this to the new table
|
||||
// Get the immage ref to toggle
|
||||
// const indicatorImageDict = document.getElementById('dictNameImg')
|
||||
// const indicatorImageDomain = document.getElementById('domainNameImg')
|
||||
// indicatorImageDict.className = 'invisible'
|
||||
// indicatorImageDomain.className = 'invisible'
|
||||
const indicatorImage = document.getElementById(`${name}Img`)
|
||||
if (orderIndex) {
|
||||
indicatorImage.className = ''
|
||||
indicatorImage.src = 'images/arrow_drop_up.svg'
|
||||
} else {
|
||||
indicatorImage.className = ''
|
||||
indicatorImage.src = 'images/arrow_drop_down.svg'
|
||||
}
|
||||
}
|
||||
|
||||
function sortName() {
|
||||
sortPlaceholder('dictName')
|
||||
}
|
||||
|
||||
function sortDomain() {
|
||||
sortPlaceholder('domainName')
|
||||
}
|
||||
|
||||
function addListenersOnRefresh() {
|
||||
document.getElementById('sortByDictName').addEventListener('click', e => {
|
||||
sortName()
|
||||
})
|
||||
document.getElementById('sortByDomainName').addEventListener('click', e => {
|
||||
sortDomain()
|
||||
})
|
||||
}
|
||||
|
||||
// initialize with listeners and DESC image
|
||||
const indicatorImageDict = document.getElementById('dictNameImg')
|
||||
indicatorImageDict.className = ''
|
||||
addListenersOnRefresh()
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/* global adjustOffsetBy, moveContent */
|
||||
|
||||
function mobileMoveContent() {
|
||||
moveContent('admin-nav-mobile')
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
try {
|
||||
adjustOffsetBy()
|
||||
mobileMoveContent()
|
||||
} catch (e) {}
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
function mobileMoveContentInit() {
|
||||
mobileMoveContent()
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
adjustOffsetBy()
|
||||
mobileMoveContentInit()
|
||||
})
|
||||
@@ -0,0 +1,553 @@
|
||||
/* global $, axios, currentPagePath, initPagination, removeAllChildNodes, transferText, tooltipTriggerList, tooltipList, reinitalizeDefaultTooltipSet, createTooltip */
|
||||
|
||||
// position correction functions
|
||||
|
||||
function adjustOffsetBy() {
|
||||
// const { offsetMain, fixedTopSection } = window.dictionaryElements
|
||||
|
||||
const offsetMain = document.querySelector('#offset-main')
|
||||
const fixedTopSection = document.querySelector('#fixed-top-section')
|
||||
|
||||
const referenceHeight = fixedTopSection.offsetHeight
|
||||
const offsetHeader = document.getElementsByClassName('offset-header')
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
// const adminNavMobile = document.getElementsByClassName('admin-nav')
|
||||
const headerPadding = document.getElementById('header-padding')
|
||||
|
||||
if (document.body.clientWidth < 1200) {
|
||||
if (offsetHeaderPadding !== null) offsetMain.style.paddingTop = `0px`
|
||||
} else {
|
||||
for (let i = 0; i < offsetHeader.length; i++) {
|
||||
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
if (headerPadding !== null) {
|
||||
const headerPaddingHeight = headerPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${headerPaddingHeight}px`
|
||||
}
|
||||
if (offsetHeaderPadding !== null) {
|
||||
const offsetHeaderHeight = offsetHeaderPadding.offsetHeight
|
||||
offsetMain.style.paddingTop = `${referenceHeight + offsetHeaderHeight}px`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
function moveContent(adminNavClassId) {
|
||||
if (document.body.clientWidth <= 1200) {
|
||||
const adminNavMobileEl = document.getElementById(adminNavClassId)
|
||||
const mobileRightHolder = document.getElementById('mobile-right-holder')
|
||||
const headerContent = document.getElementById('offset-padding')
|
||||
const secondaryButton = headerContent.querySelector('.btn-secondary')
|
||||
const primaryButton = headerContent.querySelector('.btn-primary')
|
||||
// const siteHeading = document.getElementById('site-heading')
|
||||
// const siteHeadingTextContent = siteHeading.textContent
|
||||
// const navTitle = document.getElementById('nav-title')
|
||||
// const navTitleTextContent = navTitle.textContent
|
||||
if (secondaryButton) {
|
||||
mobileRightHolder.appendChild(secondaryButton)
|
||||
// secondaryButton.style.height = '28px'
|
||||
// secondaryButton.style.width = '99px'
|
||||
// secondaryButton.style.marginRight = '10px'
|
||||
}
|
||||
if (primaryButton) {
|
||||
// if (currentPagePath === '/admin/povezave/seznam') {
|
||||
// primaryButton.style.width = '160px'
|
||||
// } else {
|
||||
// primaryButton.style.width = '99px'
|
||||
// }
|
||||
mobileRightHolder.appendChild(primaryButton)
|
||||
adminNavMobileEl.classList.add('align-items-center')
|
||||
adminNavMobileEl.classList.add('justify-content-between')
|
||||
// primaryButton.style.height = '28px'
|
||||
// primaryButton.style.marginRight = '10px'
|
||||
primaryButton.style.whiteSpace = 'nowrap'
|
||||
}
|
||||
// navTitle.textContent = siteHeadingTextContent
|
||||
// siteHeading.style.display = 'none'
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function mobileMoveContent() {
|
||||
const adminNavMobileEl = document.getElementById('admin-nav-mobile')
|
||||
const mobileRightHolder = document.getElementById('mobile-right-holder')
|
||||
const secondaryButton = document.querySelector('.header-btn-secondary')
|
||||
const primaryButton = document.querySelector('.header-btn')
|
||||
const siteHeading = document.getElementById('site-heading')
|
||||
const siteHeadingTextContent = siteHeading.textContent
|
||||
const navTitle = document.getElementById('nav-title')
|
||||
const headerContainerRight = document.querySelector(
|
||||
'.header-container-divider-right'
|
||||
)
|
||||
|
||||
try {
|
||||
if (document.body.clientWidth <= 1200) {
|
||||
if (secondaryButton) {
|
||||
mobileRightHolder.appendChild(secondaryButton)
|
||||
// secondaryButton.style.height = '28px'
|
||||
// secondaryButton.style.width = '99px'
|
||||
// secondaryButton.style.marginRight = '10px'
|
||||
}
|
||||
if (primaryButton) {
|
||||
mobileRightHolder.appendChild(primaryButton)
|
||||
adminNavMobileEl.classList.add('align-items-center')
|
||||
adminNavMobileEl.classList.add('justify-content-between')
|
||||
// primaryButton.style.height = '28px'
|
||||
// primaryButton.style.width = '99px'
|
||||
// primaryButton.style.marginRight = '10px'
|
||||
primaryButton.style.whiteSpace = 'nowrap'
|
||||
}
|
||||
navTitle.textContent = siteHeadingTextContent
|
||||
siteHeading.style.display = 'none'
|
||||
}
|
||||
if (document.body.clientWidth > 1200) {
|
||||
if (secondaryButton) {
|
||||
headerContainerRight.appendChild(secondaryButton)
|
||||
secondaryButton.style.height = ''
|
||||
secondaryButton.style.width = ''
|
||||
secondaryButton.style.marginRight = ''
|
||||
}
|
||||
if (primaryButton) {
|
||||
headerContainerRight.appendChild(primaryButton)
|
||||
adminNavMobileEl.classList.remove('align-items-center')
|
||||
adminNavMobileEl.classList.remove('justify-content-between')
|
||||
primaryButton.style.height = ''
|
||||
primaryButton.style.width = ''
|
||||
primaryButton.style.marginRight = ''
|
||||
primaryButton.style.whiteSpace = ''
|
||||
}
|
||||
|
||||
navTitle.textContent = 'Urejanje'
|
||||
siteHeading.style.display = 'block'
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
const resultsListEl = document.getElementById('results-data')
|
||||
if (resultsListEl) {
|
||||
resultsListEl.addEventListener('click', onResultClick)
|
||||
}
|
||||
const initialPage = +new URL(location).searchParams.get('p') || 1
|
||||
const updatePager = initPagination('pagination', onPageChange, initialPage)
|
||||
|
||||
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)
|
||||
reinitalizeDefaultTooltipSet()
|
||||
|
||||
/*
|
||||
try {
|
||||
textsScreenManager.manageResize()
|
||||
} catch (e) {
|
||||
console.log(
|
||||
'textsScreenManager not initialized or there is an internal error'
|
||||
)
|
||||
} */
|
||||
|
||||
return page
|
||||
} catch (error) {
|
||||
// console.log(error)
|
||||
let message = '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.'
|
||||
}
|
||||
alert(message)
|
||||
updatePager()
|
||||
}
|
||||
}
|
||||
|
||||
async function getDataForPage(page) {
|
||||
const qParams = new URL(location).searchParams
|
||||
qParams.set('p', page)
|
||||
const url = `/api/v1/search/main?${qParams}`
|
||||
|
||||
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)
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
try {
|
||||
if (tooltipTriggerList.length > 0) {
|
||||
// initialize tooltips
|
||||
tooltipList(null, '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
|
||||
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 createTooltipEl(ttElement, styles) {
|
||||
// setDynamicTooltipList([])
|
||||
|
||||
try {
|
||||
createTooltip(ttElement, ttElement.innerHTML, styles)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
function removeTooltip(ttElement) {
|
||||
try {
|
||||
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
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
function handleProperTextDisplay() {
|
||||
if (/\/iskanje/.test(currentPagePath)) {
|
||||
transferText('Iskanje po slovarjih', true)
|
||||
} else if (/\/termin/.test(currentPagePath)) {
|
||||
transferText('', true)
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
handleProperTextDisplay()
|
||||
adjustOffsetBy()
|
||||
})
|
||||
|
||||
handleProperTextDisplay()
|
||||
@@ -0,0 +1,206 @@
|
||||
/* global $, currentPagePath */
|
||||
|
||||
// const currentPagePath = location.pathname
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
initSelect()
|
||||
})
|
||||
|
||||
function initSelect() {
|
||||
const ce = {}
|
||||
window.adminElements = ce
|
||||
|
||||
ce.textDescription = document.getElementById('text-description')
|
||||
ce.headerTitle = document.getElementById('site-header-title')
|
||||
ce.fixedTopSection = document.getElementById('fixed-top-section')
|
||||
ce.offsetMain = document.getElementById('offset-main')
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
adjustOffsetBy()
|
||||
hideAndShowHeader()
|
||||
})
|
||||
window.onscroll = hideAndShowHeader
|
||||
|
||||
function hideAndShowHeader() {
|
||||
const { textDescription, headerTitle } = window.adminElements
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
|
||||
if (document.body.clientWidth > 1200) {
|
||||
if (document.documentElement.scrollTop < 50) {
|
||||
textDescription.style.display = 'block'
|
||||
headerTitle.style.display = 'block'
|
||||
if (offsetHeaderPadding !== null)
|
||||
offsetHeaderPadding.className = 'header-section-root pb-0'
|
||||
} else {
|
||||
textDescription.style.display = 'none'
|
||||
headerTitle.style.display = 'none'
|
||||
if (offsetHeaderPadding !== null)
|
||||
offsetHeaderPadding.className =
|
||||
'header-section-root offset-padding pb-0'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentPagePath === '/admin/povezave/seznam') {
|
||||
const { offsetMain } = window.adminElements
|
||||
offsetMain.addEventListener('click', handleClick)
|
||||
}
|
||||
|
||||
if (currentPagePath === '/admin/uporabniki/id_uporabnika/urejanje') {
|
||||
ce.userPasswordEl = document.getElementById('user-password')
|
||||
ce.userConfirmationPassEl = document.getElementById('user-conf-password')
|
||||
ce.buttonSaveEl = document.querySelectorAll('.btn-primary')
|
||||
ce.buttonSaveEl.forEach(el =>
|
||||
el.addEventListener('click', passwordMatchCheck)
|
||||
)
|
||||
// ce.buttonSaveEl.addEventListener('click', passwordMatchCheck)
|
||||
|
||||
function passwordMatchCheck() {
|
||||
const userPassword1 = ce.userPasswordEl.value
|
||||
const userPassword2 = ce.userConfirmationPassEl.value
|
||||
|
||||
if (userPassword1 === '') {
|
||||
alert('Prosim, vnesite geslo')
|
||||
} else if (userPassword2 === '') {
|
||||
alert('Prosim, ponovno vnesite geslo')
|
||||
} else if (userPassword1 !== userPassword2) {
|
||||
alert('Gesli se ne ujemata')
|
||||
} else {
|
||||
alert('Gesli se ujemata!')
|
||||
}
|
||||
}
|
||||
}
|
||||
adjustOffsetBy()
|
||||
}
|
||||
|
||||
function adjustOffsetBy() {
|
||||
const { offsetMain, fixedTopSection } = window.adminElements
|
||||
const referenceHeight = fixedTopSection.offsetHeight
|
||||
const offsetHeader = document.getElementsByClassName('offset-header')
|
||||
const offsetHeaderPadding = document.getElementById('offset-padding')
|
||||
const adminNavMobile = document.getElementsByClassName('admin-nav')
|
||||
const headerPadding = document.getElementById('header-padding')
|
||||
if (document.body.clientWidth < 1200) {
|
||||
for (let i = 0; i < adminNavMobile.length; i++) {
|
||||
adminNavMobile[i].style.paddingTop = `${referenceHeight}px`
|
||||
// offsetHeaderPadding.style.padding = '40px'
|
||||
// offsetMain.style.paddingTop = `${referenceHeight + 40}px`
|
||||
}
|
||||
if (offsetHeaderPadding !== null)
|
||||
offsetHeaderPadding.style.paddingTop = '20px'
|
||||
|
||||
if (headerPadding !== null) headerPadding.style.paddingTop = '60px'
|
||||
offsetMain.style.paddingTop = `0px`
|
||||
} else {
|
||||
for (let i = 0; i < offsetHeader.length; i++) {
|
||||
offsetHeader[i].style.paddingTop = `${referenceHeight}px`
|
||||
}
|
||||
if (headerPadding !== null) headerPadding.style.paddingTop = '60px'
|
||||
offsetMain.style.paddingTop = `${referenceHeight + 110}px`
|
||||
}
|
||||
}
|
||||
|
||||
function handleClick({ target }) {
|
||||
const deleteTask = target.closest('.delete-task')
|
||||
if (deleteTask) {
|
||||
deleteField(deleteTask)
|
||||
}
|
||||
}
|
||||
|
||||
function deleteField(ele) {
|
||||
const element = ele.closest('.task')
|
||||
element.remove()
|
||||
}
|
||||
|
||||
// Summernote
|
||||
|
||||
$('.summernote').summernote({
|
||||
placeholder: 'Na kratko opišite zasnovo in namen slovarja.',
|
||||
height: 300,
|
||||
minheight: 150,
|
||||
toolbar: [
|
||||
['style', ['style', 'bold', 'italic', 'underline']],
|
||||
['font', ['superscript', 'subscript']],
|
||||
['link', ['linkDialogShow']],
|
||||
['para', ['ul', 'ol']],
|
||||
['table', ['table']],
|
||||
['insert', ['picture']]
|
||||
],
|
||||
styleTags: ['p', 'h3', 'h4']
|
||||
})
|
||||
|
||||
// ELEMENT DEFINITIONS
|
||||
|
||||
const cbox = document.createElement('input')
|
||||
cbox.setAttribute('type', 'checkbox')
|
||||
cbox.checked = true
|
||||
const arrow = document.createElement('img')
|
||||
arrow.setAttribute('src', 'images/chevron-right.svg')
|
||||
// let clicked = false
|
||||
let clickedId = 'none'
|
||||
|
||||
// END ELEMENT DEFINITIONS
|
||||
|
||||
/// FUNCTION DEFINITIONS
|
||||
const createCheckBox = () => {
|
||||
const cbox = document.createElement('input')
|
||||
cbox.setAttribute('type', 'checkbox')
|
||||
cbox.checked = true
|
||||
return cbox
|
||||
}
|
||||
|
||||
const createArrowImg = () => {
|
||||
const arrow = document.createElement('img')
|
||||
arrow.setAttribute('src', 'images/chevron-right.svg')
|
||||
return arrow
|
||||
}
|
||||
|
||||
// const clickLanguageSelectSimple = e => {
|
||||
// // https://stackoverflow.com/questions/38861601/how-to-only-trigger-parent-click-event-when-a-child-is-clicked/38861760
|
||||
// const child = e.currentTarget.childNodes[0].childNodes[0]
|
||||
|
||||
// if (clicked) {
|
||||
// e.currentTarget.childNodes[0].replaceChild(arrow, child)
|
||||
// } else {
|
||||
// e.currentTarget.childNodes[0].replaceChild(cbox, child)
|
||||
// }
|
||||
// console.log(e.currentTarget.children[0][0])
|
||||
// clicked = !clicked
|
||||
// }
|
||||
|
||||
const clickLanguageSelect = e => {
|
||||
const target = e.currentTarget
|
||||
const child = target.childNodes[0].childNodes[0]
|
||||
// console.log(`rootchild: ${child}`)
|
||||
|
||||
if (clickedId === 'none') {
|
||||
// console.log(`child: ${child}`)
|
||||
target.childNodes[0].replaceChild(createCheckBox(), child)
|
||||
clickedId = target.id
|
||||
} else if (clickedId === target.id) {
|
||||
// console.log(`child: ${child}`)
|
||||
target.childNodes[0].replaceChild(createArrowImg(), child)
|
||||
clickedId = 'none'
|
||||
} else {
|
||||
const curr = document.getElementById(clickedId)
|
||||
const currchild = curr.childNodes[0].childNodes[0]
|
||||
curr.childNodes[0].replaceChild(createArrowImg(), currchild)
|
||||
target.childNodes[0].replaceChild(createCheckBox(), child)
|
||||
clickedId = target.id
|
||||
// console.log(`curr: ${currchild}`)
|
||||
// console.log(`child: ${child}`)
|
||||
}
|
||||
}
|
||||
|
||||
/// END FUNCTION DEFINITION
|
||||
|
||||
// TESTS
|
||||
|
||||
const siEltTEST = document.getElementById('sl')
|
||||
siEltTEST.onclick = clickLanguageSelect
|
||||
|
||||
const hrElttest = document.getElementById('hr')
|
||||
hrElttest.onclick = clickLanguageSelect
|
||||
|
||||
const itEltTEST = document.getElementById('it')
|
||||
itEltTEST.onclick = clickLanguageSelect
|
||||
@@ -0,0 +1,433 @@
|
||||
/* global axios */
|
||||
|
||||
/*
|
||||
TODO
|
||||
Naming convention for this file is not the best :/, due to filter extension it is
|
||||
not just language filter, but filter for many properties...
|
||||
*/
|
||||
|
||||
/** BEGIN VARIABLE CONSTRUCTION AREA */
|
||||
|
||||
// TODO insert all sections of ids
|
||||
const ids = [
|
||||
'src-lang-side',
|
||||
'dest-lang-side',
|
||||
'domain-side',
|
||||
'dict-side',
|
||||
'source-side'
|
||||
]
|
||||
// const showAllAnchors = [
|
||||
// 'show-all-src-lang-side',
|
||||
// 'show-all-dest-lang-side',
|
||||
// 'show-all-dict-side'
|
||||
// ]
|
||||
|
||||
/*
|
||||
|
||||
extracts entries from the navigation from the ID (without the hash)
|
||||
|
||||
*/
|
||||
/*
|
||||
function extract(sectionId) {
|
||||
try {
|
||||
const doc = document.querySelector(`#${sectionId}.nav-section-content`)
|
||||
const entries = doc.querySelectorAll('.nav-section-content-desc')
|
||||
return {
|
||||
id: sectionId,
|
||||
items: Array.from(entries).map(a => a.innerHTML)
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
*/
|
||||
|
||||
function extractMap(sectionId) {
|
||||
try {
|
||||
const doc = document.querySelector(`#${sectionId}.nav-section-content`)
|
||||
const entries = doc.querySelectorAll('.nav-section-content-desc')
|
||||
return {
|
||||
id: sectionId,
|
||||
items: Array.from(entries).map(a => {
|
||||
return {
|
||||
name: a.innerHTML,
|
||||
count: a.parentElement.children[2].innerHTML,
|
||||
id: a.parentNode.parentNode.id
|
||||
}
|
||||
})
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
/// / Dummy hardcoded variables
|
||||
const sourceLanguageList = extractMap(ids[0])
|
||||
const destinationLanguageList = extractMap(ids[1])
|
||||
const domainsList = extractMap(ids[2])
|
||||
const dictsList = extractMap(ids[3])
|
||||
const sourcesList = extractMap(ids[4])
|
||||
|
||||
const initializedValues = {
|
||||
'src-lang-side': sourceLanguageList,
|
||||
'dest-lang-side': destinationLanguageList,
|
||||
'domain-side': domainsList,
|
||||
'dict-side': dictsList,
|
||||
'source-side': sourcesList
|
||||
}
|
||||
|
||||
const selectedIds = {
|
||||
/*
|
||||
'src-lang-side': [],
|
||||
'dest-lang-side': [],
|
||||
'domain-side': [],
|
||||
'dict-side': [],
|
||||
'source-side': []
|
||||
*/
|
||||
}
|
||||
|
||||
function fillSelectedID(idSec) {
|
||||
Array.from(document.getElementById(idSec).children).forEach(child => {
|
||||
if (child.tagName === 'LI') {
|
||||
if (
|
||||
child.children[0].children[0].children[0].getAttribute('src') ===
|
||||
'/images/square-checkbox-solid.svg'
|
||||
) {
|
||||
selectedIds[idSec].push(child.id)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function fillSelectedIDs() {
|
||||
ids.forEach(idSec => {
|
||||
fillSelectedID(idSec)
|
||||
})
|
||||
}
|
||||
|
||||
function initSelectedIds() {
|
||||
ids.forEach(idSec => {
|
||||
selectedIds[idSec] = []
|
||||
})
|
||||
}
|
||||
|
||||
initSelectedIds()
|
||||
fillSelectedIDs()
|
||||
|
||||
/** referenced to: select more buttons */
|
||||
const selectMoreIDs = [
|
||||
'select-src-langs',
|
||||
'select-dest-langs',
|
||||
'select-domains',
|
||||
'select-dicts',
|
||||
'select-sources'
|
||||
]
|
||||
|
||||
const queryOrderedArr = {
|
||||
'src-lang-side': 'sl',
|
||||
'dest-lang-side': 'tl',
|
||||
'domain-side': 'pd',
|
||||
'dict-side': 'd',
|
||||
'source-side': 's'
|
||||
}
|
||||
|
||||
const url = new URL(window.location.href)
|
||||
|
||||
/** ID of the filter section */
|
||||
let sectionIDBattery = -1
|
||||
|
||||
/** END VARIABLE CONSTRUCTION AREA */
|
||||
|
||||
function createListItemBlockForModal(id, name, amount, sectionId) {
|
||||
const li = document.createElement('li')
|
||||
const div = document.createElement('div')
|
||||
li.appendChild(div)
|
||||
const input = document.createElement('input')
|
||||
input.type = 'checkbox'
|
||||
input.id = id
|
||||
|
||||
if (selectedIds[sectionId].filter(e => e === id).length > 0) {
|
||||
input.checked = true
|
||||
}
|
||||
|
||||
div.appendChild(input)
|
||||
const label = document.createElement('label')
|
||||
label.setAttribute('for', id)
|
||||
label.innerHTML = name
|
||||
label.classList = 'nav-modal-content-desc checked'
|
||||
li.appendChild(label)
|
||||
const amnt = document.createElement('span')
|
||||
amnt.innerHTML = amount
|
||||
label.appendChild(amnt)
|
||||
|
||||
return li
|
||||
}
|
||||
|
||||
function linkToModal(element) {
|
||||
const modalListRoot = document.querySelector('#modal-list')
|
||||
modalListRoot.appendChild(element)
|
||||
}
|
||||
|
||||
function initModalList(id, list) {
|
||||
list.forEach(l =>
|
||||
linkToModal(createListItemBlockForModal(l.id, l.name, l.hits, id))
|
||||
)
|
||||
sectionIDBattery = id
|
||||
}
|
||||
|
||||
function cleanOldList() {
|
||||
const modalListRoot = document.querySelector('#modal-list')
|
||||
modalListRoot.innerHTML = ''
|
||||
}
|
||||
|
||||
async function selectMoreListener(event) {
|
||||
const idstring = `${event.currentTarget.id
|
||||
.replace('select-', '')
|
||||
.slice(0, -1)
|
||||
.concat('-side')}`
|
||||
// console.log(extractMap(idstring))
|
||||
|
||||
// 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 }
|
||||
|
||||
const currentURL = new URL(window.location.href)
|
||||
const searchParams = currentURL.searchParams
|
||||
|
||||
searchParams.set('selectedFilter', idToSearchFiltersMapper(idstring))
|
||||
|
||||
const url = `/api/v1/search/term-filters?${searchParams.toString()}`
|
||||
const { data } = await axios.get(url)
|
||||
|
||||
// const parsed = JSON.parse(event.currentTarget.dataset.aggregationInfo ?? '[]')
|
||||
|
||||
allAggregationData.items = data[idToSearchFiltersMapper(idstring)]
|
||||
|
||||
cleanOldList()
|
||||
initModalList(allAggregationData.id, allAggregationData.items)
|
||||
}
|
||||
|
||||
function idToSearchFiltersMapper(inpt) {
|
||||
const mappings = {
|
||||
'src-lang-side': 'sourceLanguages',
|
||||
'dest-lang-side': 'targetLanguages',
|
||||
'domain-side': 'primaryDomains',
|
||||
'dict-side': 'dictionaries',
|
||||
'source-side': 'sources'
|
||||
}
|
||||
|
||||
return mappings[inpt]
|
||||
}
|
||||
|
||||
function createSideMenuElement(id, name, count, isSelected) {
|
||||
const child = document.createElement('li')
|
||||
child.id = id
|
||||
const anchr = document.createElement('a')
|
||||
anchr.classList = 'sel-anchr'
|
||||
anchr.setAttribute('href', '#')
|
||||
child.appendChild(anchr)
|
||||
const divforimg = document.createElement('div')
|
||||
const img = document.createElement('img')
|
||||
divforimg.appendChild(img)
|
||||
|
||||
if (isSelected) {
|
||||
img.setAttribute('src', '/images/square-checkbox-solid.svg')
|
||||
} else {
|
||||
img.setAttribute('src', '/images/chevron-right.svg')
|
||||
}
|
||||
|
||||
const nameSpan = document.createElement('span')
|
||||
nameSpan.innerHTML = name
|
||||
nameSpan.classList = 'nav-section-content-desc'
|
||||
const countSpan = document.createElement('span')
|
||||
countSpan.innerHTML = count
|
||||
anchr.appendChild(divforimg)
|
||||
anchr.appendChild(nameSpan)
|
||||
anchr.appendChild(countSpan)
|
||||
|
||||
return child
|
||||
}
|
||||
|
||||
selectMoreIDs.forEach(button => {
|
||||
const buttonElement = document.querySelector(`#${button}`)
|
||||
buttonElement.addEventListener('click', selectMoreListener)
|
||||
})
|
||||
|
||||
sectionIDBattery = -1
|
||||
|
||||
/// logic to update selectedIDs state of checked items
|
||||
function checkOrUncheck(sectionId, id) {
|
||||
const checked = selectedIds[sectionId].filter(e => id === e)
|
||||
|
||||
if (checked.length > 0) {
|
||||
selectedIds[sectionId] = selectedIds[sectionId].filter(e => id !== e)
|
||||
} else {
|
||||
selectedIds[sectionId].push(id)
|
||||
}
|
||||
}
|
||||
|
||||
function listener(cnt) {
|
||||
return e => {
|
||||
const searchParams = url.searchParams
|
||||
searchParams.append(
|
||||
queryOrderedArr[Object.keys(queryOrderedArr)[cnt]],
|
||||
e.currentTarget.parentElement.id
|
||||
)
|
||||
// console.log(url.searchParams.getAll('sl'))
|
||||
window.location.href = url
|
||||
}
|
||||
}
|
||||
|
||||
function finishSelectingFromModal(e) {
|
||||
const newValues = []
|
||||
Array.from(document.querySelector('#modal-list').children).forEach(e => {
|
||||
const checkField = e.children[0].children[0]
|
||||
const labelId = e.children[1]
|
||||
|
||||
// console.log(checkField, labelId, labelId.getAttribute('for'))
|
||||
if (checkField.checked) {
|
||||
newValues.push(labelId.getAttribute('for'))
|
||||
}
|
||||
})
|
||||
const url = new URL(window.location.href)
|
||||
const searchParams = url.searchParams
|
||||
searchParams.delete(queryOrderedArr[sectionIDBattery])
|
||||
newValues.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-', '')
|
||||
// console.log(id)
|
||||
rePlotAndCheck(id, [], true)
|
||||
clearModalFiltersWID(id)
|
||||
}
|
||||
|
||||
function initClickableForList(sectionId) {
|
||||
let QOACounter = 0
|
||||
document.querySelectorAll(`#${sectionId}`).forEach(e => {
|
||||
e.querySelectorAll('a.sel-anchr').forEach(a => {
|
||||
a.addEventListener('click', listener(QOACounter))
|
||||
})
|
||||
QOACounter++
|
||||
})
|
||||
}
|
||||
|
||||
/* function applied to reset filter(s) or select modal return state */
|
||||
function rePlotAndCheck(sectionId, selectedIdsArray, plotInverse = false) {
|
||||
const doc = document.querySelector(`#${sectionId}.nav-section-content`)
|
||||
doc.innerHTML = ''
|
||||
|
||||
initializedValues[sectionId].items.forEach(el => {
|
||||
const isSelected = selectedIdsArray.filter(e => e === el.id).length > 0
|
||||
if (isSelected) {
|
||||
doc.appendChild(
|
||||
createSideMenuElement(el.id, el.name, el.count, isSelected)
|
||||
)
|
||||
} else if (plotInverse) {
|
||||
doc.appendChild(
|
||||
createSideMenuElement(el.id, el.name, el.count, isSelected)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
if (doc.children.length < 1) {
|
||||
initializedValues[sectionId].items.forEach(el => {
|
||||
doc.appendChild(createSideMenuElement(el.id, el.name, el.count, false))
|
||||
})
|
||||
}
|
||||
|
||||
initClickableForList(sectionId)
|
||||
|
||||
const anchr = document.createElement('a')
|
||||
anchr.classList = ' showall d-none'
|
||||
anchr.id = `show-all-${sectionId}`
|
||||
anchr.href = '#'
|
||||
|
||||
const img = document.createElement('img')
|
||||
img.setAttribute('src', '/images/chevron-left-blue.svg')
|
||||
const span = document.createElement('span')
|
||||
span.innerHTML = 'PRIKAŽI VSE'
|
||||
|
||||
anchr.appendChild(img)
|
||||
anchr.appendChild(span)
|
||||
|
||||
anchr.addEventListener('click', reRenderSpecific)
|
||||
|
||||
doc.appendChild(anchr)
|
||||
|
||||
if (selectedIdsArray.length > 0) {
|
||||
const anchr = document.querySelector(`#show-all-${sectionId}`)
|
||||
// console.log(`#show-all-${sectionId}`)
|
||||
anchr.classList = 'showall'
|
||||
}
|
||||
}
|
||||
|
||||
/// TODO, some better option than global variable sectionIDBattery?
|
||||
function selectFromModal(event) {
|
||||
// console.log(event.target.id)
|
||||
if (event.target.id) {
|
||||
checkOrUncheck(sectionIDBattery, event.target.id)
|
||||
}
|
||||
}
|
||||
|
||||
function clearModalFilters() {
|
||||
Array.from(document.querySelector('#modal-list').children).forEach(e => {
|
||||
e.children[0].children[0].checked = false
|
||||
})
|
||||
selectedIds[sectionIDBattery] = []
|
||||
}
|
||||
|
||||
function clearModalFiltersWID(id) {
|
||||
Array.from(document.querySelector('#modal-list').children).forEach(e => {
|
||||
e.children[0].children[0].checked = false
|
||||
})
|
||||
selectedIds[id] = []
|
||||
}
|
||||
|
||||
function initializeClickables() {
|
||||
let QOACounter = 0
|
||||
ids.forEach(element => {
|
||||
document.querySelectorAll(`#${element}`).forEach(e => {
|
||||
e.querySelectorAll('a.sel-anchr').forEach(a => {
|
||||
a.addEventListener('click', listener(QOACounter))
|
||||
})
|
||||
})
|
||||
QOACounter++
|
||||
})
|
||||
document
|
||||
.querySelector('#modal-list')
|
||||
.addEventListener('click', selectFromModal)
|
||||
document
|
||||
.querySelector('#sf-modal-button')
|
||||
.addEventListener('click', finishSelectingFromModal)
|
||||
|
||||
document.querySelector('#ccf').addEventListener('click', clearModalFilters)
|
||||
|
||||
Array.from(document.querySelectorAll('.showall')).forEach(e =>
|
||||
e.addEventListener('click', event => {
|
||||
sectionIDBattery = event.currentTarget.id.replace('show-all-', '')
|
||||
const url = new URL(window.location.href)
|
||||
const searchParams = url.searchParams
|
||||
searchParams.delete(queryOrderedArr[sectionIDBattery])
|
||||
window.location.href = url
|
||||
})
|
||||
)
|
||||
|
||||
document.querySelector('#clear-filters').addEventListener('click', e => {
|
||||
const url = new URL(window.location.href)
|
||||
const searchParams = url.searchParams
|
||||
Object.keys(queryOrderedArr).forEach(queryParamKey => {
|
||||
searchParams.delete(queryOrderedArr[queryParamKey])
|
||||
})
|
||||
window.location.href = url
|
||||
})
|
||||
}
|
||||
|
||||
// initModalList('id1', langsMapModal)
|
||||
|
||||
/// global run
|
||||
|
||||
initializeClickables()
|
||||
@@ -0,0 +1,110 @@
|
||||
/* global bootstrap */
|
||||
|
||||
let tooltipTriggerList = []
|
||||
let dynamicTooltipList
|
||||
|
||||
function setDynamicTooltipList(value) {
|
||||
dynamicTooltipList = value
|
||||
}
|
||||
dynamicTooltipList = []
|
||||
|
||||
resetTooltipTriggerList() // init
|
||||
|
||||
/**
|
||||
* tooltipList usage doc:
|
||||
* tooltipList is expected to have a list of items that will be put on to
|
||||
* and HTML unordered list. The tooltip element is required to have the
|
||||
* following attribute:
|
||||
* data-tooltip-content -> list of items seperated with ;
|
||||
*
|
||||
*/
|
||||
|
||||
// Presumably used in other files, like consultancy.js.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const tooltipListWOL = styles => {
|
||||
generateTooltipWithOrderedList(tooltipTriggerList, styles)
|
||||
}
|
||||
|
||||
const tooltipList = (content, styles) => {
|
||||
generateTooltipWithStyles(tooltipTriggerList, content, styles)
|
||||
}
|
||||
|
||||
function generateTooltipWithOrderedList(list = tooltipTriggerList, styles) {
|
||||
return generateTooltipBase(list, function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl, {
|
||||
html: true,
|
||||
title: () => {
|
||||
let content = '<ul>'
|
||||
|
||||
content += tooltipTriggerEl
|
||||
.getAttribute('data-tooltip-content')
|
||||
.split(',')
|
||||
.reduce((acc, value) => {
|
||||
if (value) {
|
||||
return `
|
||||
${acc}
|
||||
<li>
|
||||
${value}
|
||||
</li>
|
||||
`
|
||||
} else {
|
||||
return acc
|
||||
}
|
||||
}, '')
|
||||
|
||||
content += '</ul>'
|
||||
|
||||
return content
|
||||
},
|
||||
customClass: styles
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function generateTooltipWithStyles(
|
||||
list = tooltipTriggerList,
|
||||
content = el => {
|
||||
el.getAttribute('data-tooltip-content')
|
||||
},
|
||||
styles = 'tooltip-list-default-class'
|
||||
) {
|
||||
let nonEmptyContent
|
||||
if (!content) {
|
||||
nonEmptyContent = el => {
|
||||
el.getAttribute('data-tooltip-content')
|
||||
}
|
||||
} else {
|
||||
nonEmptyContent = content
|
||||
}
|
||||
|
||||
return generateTooltipBase(list, function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl, {
|
||||
html: true,
|
||||
title: nonEmptyContent,
|
||||
customClass: styles
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function generateTooltipBase(list, fn) {
|
||||
return list.map(fn)
|
||||
}
|
||||
|
||||
function resetTooltipTriggerList() {
|
||||
tooltipTriggerList = [].slice.call(
|
||||
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
||||
)
|
||||
}
|
||||
|
||||
function reinitalizeDefaultTooltipSet() {
|
||||
resetTooltipTriggerList()
|
||||
tooltipList()
|
||||
}
|
||||
|
||||
function createTooltip(element, content, styles) {
|
||||
return new bootstrap.Tooltip(element, {
|
||||
html: true,
|
||||
title: content,
|
||||
customClass: styles
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* global trustedTypes, DOMPurify */
|
||||
if (window.trustedTypes && trustedTypes.createPolicy) {
|
||||
trustedTypes.createPolicy('default', {
|
||||
createHTML: (string, sink) => {
|
||||
const trustedType = DOMPurify.sanitize(string, {
|
||||
RETURN_TRUSTED_TYPE: true
|
||||
})
|
||||
|
||||
console.log('REMOVED:', DOMPurify.removed) // eslint-disable-line
|
||||
|
||||
return trustedType
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/* global axios */
|
||||
|
||||
function autoGrow(element) {
|
||||
element.style.height = '5px'
|
||||
element.style.height = element.scrollHeight + 'px'
|
||||
}
|
||||
|
||||
// FIREFOX ISSUE FIX
|
||||
const firefoxIssueyBoi = document.querySelector('.institution-input')
|
||||
if (firefoxIssueyBoi) autoGrow(firefoxIssueyBoi)
|
||||
// END FIREFOX ISSUE FIX
|
||||
|
||||
function autoGrowListener(e) {
|
||||
autoGrow(e.target)
|
||||
}
|
||||
|
||||
// (Lineheight) (measurement) * #lines + (padding) (measurementforpadding)
|
||||
function minHeightCalcRem(
|
||||
lineheightSize,
|
||||
numberOfLines,
|
||||
paddingTopAndBottomSize,
|
||||
lineheightSizeMeasurement = 'rem',
|
||||
paddingTopAndBottomSizeMeasurement = 'px'
|
||||
) {
|
||||
return `calc(${lineheightSize}${lineheightSizeMeasurement}*${numberOfLines} + ${paddingTopAndBottomSize}${paddingTopAndBottomSizeMeasurement})`
|
||||
}
|
||||
|
||||
// COMMENTED CODE IS THE INITIAL STRUCTURE BEFORE PATCHING
|
||||
/*
|
||||
function abortEditing(
|
||||
btnGrp,
|
||||
oldButtons,
|
||||
areaEl,
|
||||
translationEl,
|
||||
removeSpecifics = []
|
||||
) {
|
||||
btnGrp.className = 'd-none'
|
||||
oldButtons.style.display = 'block'
|
||||
const getRow = btnGrp.parentElement.parentElement
|
||||
getRow.classList.remove('selected-row')
|
||||
const getInputs = getRow.querySelectorAll('.w-50')
|
||||
removeSpecifics.forEach(el => el.remove())
|
||||
getInputs.forEach(el => el.parentElement.remove())
|
||||
areaEl.style.display = 'table-cell'
|
||||
translationEl.style.display = 'table-cell'
|
||||
}
|
||||
*/
|
||||
|
||||
function abortConsultancyUserEditing(fieldInfo) {
|
||||
fieldInfo.newButtonGroup.className = 'd-none'
|
||||
fieldInfo.tableButtons.style.display = 'block'
|
||||
const getRow = fieldInfo.newButtonGroup.parentElement.parentElement
|
||||
getRow.classList.remove('selected-row')
|
||||
const getInputs = getRow.querySelectorAll('.w-50')
|
||||
fieldInfo.tdName.remove()
|
||||
getInputs.forEach(el => el.parentElement.remove())
|
||||
fieldInfo.tDataDomain.style.display = 'table-cell'
|
||||
fieldInfo.tDataName.style.display = 'table-cell'
|
||||
}
|
||||
|
||||
/*
|
||||
function saveChanges(
|
||||
btnGrp,
|
||||
inputDomain,
|
||||
inputTranslation,
|
||||
oldButtons,
|
||||
tDataDomain,
|
||||
tDataTranslation
|
||||
) {
|
||||
const inputDomainNewValue = inputDomain.value
|
||||
const inputTranslationNewValue = inputTranslation.value
|
||||
btnGrp.className = 'd-none'
|
||||
oldButtons.style.display = 'block'
|
||||
const getRow = btnGrp.parentElement.parentElement
|
||||
getRow.classList.remove('selected-row')
|
||||
inputDomain.parentElement.remove()
|
||||
inputTranslation.parentElement.remove()
|
||||
tDataDomain.style.display = 'table-cell'
|
||||
tDataDomain.textContent = inputDomainNewValue
|
||||
tDataTranslation.style.display = 'table-cell'
|
||||
tDataTranslation.textContent = inputTranslationNewValue
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// Presumably used in other files, like consultancy.js.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function inputFieldsChecker() {
|
||||
const { inputDomainEl, inputTranslationEl } = window.adminElements
|
||||
const addAreaButton = document.getElementById('add-area')
|
||||
if (inputDomainEl.value.length && inputTranslationEl.value.length) {
|
||||
addAreaButton.disabled = false
|
||||
} else {
|
||||
addAreaButton.disabled = true
|
||||
}
|
||||
}
|
||||
|
||||
function saveConsultantFrontend(fieldInfo) {
|
||||
// Please optimize this patched code in further dev
|
||||
fieldInfo.tDataDomain.innerHTML = fieldInfo.inputDomain.value
|
||||
? fieldInfo.inputDomain.value
|
||||
: ''
|
||||
abortConsultancyUserEditing(fieldInfo)
|
||||
}
|
||||
|
||||
function saveConsultantDomain(fieldInfo) {
|
||||
const data = {
|
||||
id: fieldInfo.tDataName.parentElement.id,
|
||||
value: fieldInfo.inputDomain.value
|
||||
}
|
||||
|
||||
// procedure to store DB changes
|
||||
axios
|
||||
.put('/api/v1/consultancy/update-consultant-domain', data)
|
||||
.then(() => {
|
||||
// On success, update frontend
|
||||
saveConsultantFrontend(fieldInfo)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
|
||||
function editRowBodyForConsultancy(fieldInfo) {
|
||||
fieldInfo.getRow.className = 'selected-row'
|
||||
fieldInfo.tableButtons.style.display = 'none'
|
||||
|
||||
fieldInfo.inputDomain.className = 'form-control w-50'
|
||||
fieldInfo.inputDomain.value = fieldInfo.tDataDomainText
|
||||
|
||||
fieldInfo.tdName.innerHTML = fieldInfo.tDataNameText
|
||||
// tDataDomain.remove()
|
||||
fieldInfo.tDataDomain.style.display = 'none'
|
||||
|
||||
// Please optimize this patched code in further dev
|
||||
if (fieldInfo.tdDomain.parentElement !== fieldInfo.getRow) {
|
||||
fieldInfo.tdDomain.appendChild(fieldInfo.inputDomain)
|
||||
fieldInfo.getRow.insertBefore(fieldInfo.tdDomain, fieldInfo.tDataButtons)
|
||||
} else {
|
||||
fieldInfo.tDataButtons.style.display = 'table-cell'
|
||||
}
|
||||
|
||||
if (fieldInfo.tdName.parentElement !== fieldInfo.getRow) {
|
||||
fieldInfo.getRow.insertBefore(fieldInfo.tdName, fieldInfo.tDataName)
|
||||
} else {
|
||||
fieldInfo.tDataName.style.display = 'table-cell'
|
||||
}
|
||||
|
||||
// tDataTranslation.remove()
|
||||
fieldInfo.tDataName.style.display = 'none'
|
||||
const buttonsGroup = fieldInfo.getRow.querySelector('.buttons-group')
|
||||
const newButtonGroup = document.createElement('div')
|
||||
const cancelButton = document.createElement('button')
|
||||
const saveButton = document.createElement('button')
|
||||
fieldInfo.buttonsGroup = buttonsGroup
|
||||
fieldInfo.newButtonGroup = newButtonGroup
|
||||
fieldInfo.cancelButton = cancelButton
|
||||
fieldInfo.saveButton = saveButton
|
||||
cancelButton.textContent = '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.className = 'btn btn-primary'
|
||||
saveButton.style.height = '33px'
|
||||
saveButton.style.width = '105px'
|
||||
saveButton.addEventListener('click', () => saveConsultantDomain(fieldInfo))
|
||||
newButtonGroup.className = 'd-flex justify-content-end me-3'
|
||||
newButtonGroup.appendChild(cancelButton)
|
||||
newButtonGroup.appendChild(saveButton)
|
||||
buttonsGroup.insertBefore(newButtonGroup, fieldInfo.tableButtons)
|
||||
}
|
||||
|
||||
// Presumably used in other files, like consultancy.js.
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
function handleDomainsClickForConsultancy({ target }) {
|
||||
const editRow = target.closest('.edit-row-btn')
|
||||
const deleteRow = target.closest('.delete-row-btn')
|
||||
const tableButtons = target.closest('.table-buttons')
|
||||
if (deleteRow) {
|
||||
const getRow = deleteRow.parentElement.parentElement.parentElement
|
||||
const body = { data: { id: getRow.id } }
|
||||
const modalUseBtn = document.getElementById('modal-use-btn')
|
||||
modalUseBtn.addEventListener('click', () => {
|
||||
axios
|
||||
.delete('/api/v1/consultancy/delete-consultant', body)
|
||||
.then(() => {
|
||||
getRow.remove()
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Cannot delete entry, reason: ' + err)
|
||||
})
|
||||
})
|
||||
}
|
||||
if (editRow) {
|
||||
const getRow = editRow.parentElement.parentElement.parentElement
|
||||
const tDataDomain = getRow.querySelector('.tdata-area')
|
||||
const tDataName = getRow.querySelector('.tdata-name')
|
||||
const tDataButtons = getRow.querySelector('.buttons-group')
|
||||
const tDataDomainText = tDataDomain.textContent
|
||||
const tDataNameText = tDataName.textContent
|
||||
const tdDomain = document.createElement('td')
|
||||
const inputDomain = document.createElement('input')
|
||||
const tdName = document.createElement('td')
|
||||
|
||||
const fieldInfo = {
|
||||
editRow,
|
||||
deleteRow,
|
||||
tableButtons,
|
||||
getRow,
|
||||
tDataDomain,
|
||||
tDataName,
|
||||
tDataButtons,
|
||||
tDataDomainText,
|
||||
tDataNameText,
|
||||
tdDomain,
|
||||
inputDomain,
|
||||
tdName
|
||||
}
|
||||
|
||||
editRowBodyForConsultancy(fieldInfo)
|
||||
|
||||
/*
|
||||
console.log(`${editRow} ${deleteRow} ${tableButtons}
|
||||
- ${tDataDomain}
|
||||
- ${getRow} ${tDataName} ${tDataButtons}
|
||||
- ${tDataDomainText} ${tDataNameText} ${tdDomain}
|
||||
- ${inputDomain} ${inputDomain} ${tdName}
|
||||
`)
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/* ========= specific pages logic ========= */
|
||||
|
||||
// pages/consultancy/ask.pug
|
||||
|
||||
try {
|
||||
document.querySelectorAll('.r-3').forEach(element => {
|
||||
element.style.minHeight = minHeightCalcRem(1.5, 3, 12) // calculation of 16px(1rem) for 3 lines -> 3 * 24 (line height 24px -> 1.5rem) + 12 (padding bot + top)
|
||||
element.addEventListener('input', autoGrowListener)
|
||||
})
|
||||
|
||||
const elt = document.querySelector('.institution-input')
|
||||
elt.style.minHeight = minHeightCalcRem(1.5, 1, 12) // calculation of 16px(1rem) for 1 line -> 1 * 24 (line height 24px -> 1.5rem) + 12 (padding bot + top)
|
||||
elt.addEventListener('input', autoGrowListener)
|
||||
} catch (e) {
|
||||
// other than ask.pug file is probably going to error out here
|
||||
}
|
||||
|
||||
// end pages/consultancy/ask.pug
|
||||
|
||||
try {
|
||||
const elt = document.querySelector('#opinion')
|
||||
elt.style.minHeight = minHeightCalcRem(1.5, 4, 12) // calculation of 16px(1rem) for 1 line -> 1 * 24 (line height 24px -> 1.5rem) + 12 (padding bot + top)
|
||||
} catch (e) {}
|
||||
Reference in New Issue
Block a user