[ref] Refactor js/etersoft/timer.js. #14950

parent 103d7dc8
//Номер баги //Номер баги
var bugId = getIdFromUrl() || getBugIdFromField(); let bugId = getIdFromUrl() || getBugIdFromField();
// Если id нет, то мы имеем дело с новой багой // Если id нет, то мы имеем дело с новой багой
if (!bugId) { if (!bugId) {
// Присвоим текущее время, чтобы при создании следующей баги значения не сохранились const currentTime = new Date().getTime()
bugId = "c" + new Date().getTime(); // Присвоим текущее время, чтобы при создании следующей баги значения не сохранились
bugId = `c${currentTime}`;
} }
var protocol = window.location.protocol; // получим протокол
const {
protocol
} = window.location;
//Изменение баги //Изменение баги
var changed_remain = 0; var changed_remain = 0;
//Создание баги // Создание баги
var etersoft_create = window.location.href.search("enter") !== -1 ? 1 : 0; const isBugCreation = window.location.pathname.includes("enter");
// Объект таймера, создается при инициализации function initTimer(config) {
// Подробнее про таймер см. timer_common.js // Показываем время только сотрудникам Etersoft
var timer; if (!isEtersoft()) return;
// достанем все необходимые параметры
// для конфигурирования таймера
const {
updateInterval,
selector,
protocol,
bugId,
udpateTimerCallback
} = config
// покажем сам таймер
document.querySelector(selector).style.display = "block";
// Интервал обновления таймера в мс, на точность не влияет const timer = new Timer(`bug:${protocol}${bugId}`, udpateTimerCallback);
var UPDATE_INTERVAL = 1000; timer.setAutoUpdate(updateInterval);
function initTimer() { return timer
// Показываем время только сотрудникам Etersoft }
if (!isetersoft()) return;
// Конфиг для валидации комментарии
const VALIDATION_CONFIG = {
minLength: 9,
maxTime: 8,
}
document.getElementById("timerblock").style.display = "block"; // Конфиг таймера
timer = new Timer("bug:" + protocol + bugId, updateTimer); const TIMER_CONFIG = {
timer.setAutoUpdate(UPDATE_INTERVAL); // Интервал обновления таймера в мс, на точность не влияет
updateInterval: 1000,
// Селектор элемента, в котором лежит сам таймер
selector: "#timerblock",
// протокол
protocol,
// номер баги
bugId,
// функция updateTimer
udpateTimerCallback: updateTimer
} }
// Объект таймера, создается при инициализации
// Подробнее про таймер см. timer_common.js
const timer = initTimer(TIMER_CONFIG);
// this при вызове - объект таймера // this при вызове - объект таймера
function updateTimer() { function updateTimer() {
setPauseDisplay(this.isPaused()); setPauseDisplay(this.isPaused());
document.querySelector("#timespent").value = this.getFormattedString(); document.querySelector("#timespent").value = this.getFormattedString();
} }
//Установка в поле отработанного времени в минутах // Установка в поле отработанного времени в минутах
function setWorkTime(manualTime) { function setWorkTime(manualTime) {
var minutes = Math.ceil(timer.getElapsedSeconds() / 60); const minutes = Math.ceil(timer.getElapsedSeconds() / 60);
document.querySelector("#realworktime").value = manualTime document.querySelector("#realworktime").value = manualTime ?
? manualTime manualTime :
: minutes; minutes;
} }
function setPauseDisplay(pause) { // переключение видимости по селектору
document.querySelector("#timespent").style.color = pause ? "gray" : "black"; function toggleVisibility(selector, isHidden) {
document.querySelector("#timer_pause").style.visibility = pause document.querySelector(selector).style.visibility = isHidden ?
? "hidden" "hidden" :
: "visible"; "visible"
document.querySelector("#timer_play").style.visibility = pause
? "visible"
: "hidden";
} }
///////////////////////////////////////////////////// // меняем вид таймера при паузе
function showDiv() { function setPauseDisplay(pause) {
document.querySelector("#timeQuestionDiv").style.display = "block"; document.querySelector("#timespent").style.color = pause ? "gray" : "black";
document.querySelector("#realworktime").focus();
}
function closeDiv() { // прячем кнопку для паузы
document.querySelector("#timeQuestionDiv").style.display = "none"; toggleVisibility("#timer_pause", pause);
// показываем кнопку для включения
toggleVisibility("#timer_play", !pause);
} }
/* Получение номера баги из поля */ // Получение номера баги из поля
function getBugIdFromField() { function getBugIdFromField() {
var field = document.querySelector("#changeform input[name=id]"); const field = document.querySelector("#changeform input[name=id]");
if (field) {
return parseInt(field.value); if (field) {
} return parseInt(field.value);
return false; }
return false;
} }
//////////////////////////////////////////// // Является ли пользователь сотрудником Etersoft
function isEtersoft() {
const email = document.getElementById("useremail").className;
//Является ли пользователь сотрудником Etersoft if (!email) return false;
function isetersoft() {
var email = document.getElementById("useremail").className;
if (!email) return false;
var domain = email.split("@")[1]; const domain = email.split("@")[1];
return domain === "etersoft.ru"; return domain === "etersoft.ru";
} }
//Является ли пользователь ответственным // Является ли пользователь ответственным
function isworker() { function isWorker() {
var useremail = document.getElementById("useremail"); const email = document.getElementById("useremail").className;
var assigntoemail = document.getElementById("assigntoemail"); const assignemail = document.getElementById("assigntoemail").className;
var email = useremail.className;
var assignemail = assigntoemail.className;
return email == assignemail; return email == assignemail;
} }
window.addEventListener("load", function() { // функция для получения времени с таймера в минутах
function getTimespentValue() {
return Math.round(timer.getElapsedSeconds() / 60);
}
function getTimespentValue() { // лямбда для получения числового значения времени по селектору
let timespent = document.querySelector("#timespent").value; const parseTimeInt = (selector) => parseInt(document.querySelector(selector).value);
let timespentValue = timespent.split(":");
// let's calc how many time is spent in minutes // лямбда для получения числового значения времени из элемента
let hours = parseInt(timespentValue[0]) * 60; const parseTimeIntFromData = (elem) => parseInt(elem.dataset["time"]);
let minutes = parseInt(timespentValue[1]);
let seconds = Math.round(parseInt(timespentValue[2]) / 60);
timespentValue = hours + minutes + seconds; // лямбда для перевода времени из минут в часы
const calcTimeValue = (time) => Math.ceil((time / 60) * 100) / 100;
return timespentValue; // функция для обновления оставшегося времени
} function updateRemainingTime(workTimeValue) {
// получаем estimatedTime
const estimatedTimeElement = document.querySelector('#estimated_time');
const workedTimeElement = document.querySelector('.bz_time_tracking_table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(3)');
// add listener for comment commit if (estimatedTimeElement && workedTimeElement) {
let openButton = document.querySelector("#commit"); const estimatedTime = Number(estimatedTimeElement.value);
let closeButton = document.querySelectorAll("#timeQuestionDiv .close");
let dialog = document.querySelector("#timeQuestionDiv");
openButton.addEventListener("click", function(event) { // получаем отработанное время
// cancel form submiting const workedTime = Number(workedTimeElement.innerText);
event.preventDefault();
if (!isetersoft()) { // пересчитанное отработанное время
const comment = document.querySelector('#comment').value.length; const updatedWorkedTime = ((workedTime * 100) + (workTimeValue * 100)) / 100;
// считаем сколько осталось
const remainingTimeValue = Math.ceil(((estimatedTime * 100) - (updatedWorkedTime * 100))) / 100;
// обновляем оставшееся время
document.querySelector("#remaining_time").value = remainingTimeValue > 0 ? remainingTimeValue : 0;
}
}
// функция для отправки комментария
function submitComment(commentData) {
const validatedComment = validateComment(...commentData);
const { error, text } = validatedComment;
if (!comment) { if (error) {
alert('Поле комментария не может быть пустым!'); alert(text);
return return;
} }
const bugForm = isBugCreation ? "#Create" : "#changeform";
document.querySelector(bugForm).submit();
timer.clear();
localStorage.removeItem("time");
}
// функция для валидации комментария
function validateComment(comment, workTimeValue, productiveTimeValue, validationConfig = VALIDATION_CONFIG) {
const commentLength = comment.length;
const isMinLength = commentLength > validationConfig.minLength;
const isMaxWorkTime = workTimeValue > validationConfig.maxTime;
const isMaxProductiveTime = productiveTimeValue > validationConfig.maxTime;
const bugForm = etersoft_create === 1 ? "#Create" : "#changeform"; const isProductiveTimeHigher = productiveTimeValue > workTimeValue;
document.querySelector(bugForm).submit();
return const isNotCommentTooShort = productiveTimeValue > 2 &&
comment.length < productiveTimeValue * 60;
const isZeroTime = !comment.length && workTimeValue === 0 && productiveTimeValue === 0;
let error = "";
if (commentLength) {
if (!isMinLength) {
error = "Слишком короткий комментарий";
} else if (isMaxWorkTime || isMaxProductiveTime) {
error = "Недопустимо указывать отработанное/продуктивное время более восьми часов. Правильным следованием рабочему процессу было бы выполнение работы по частям, о каждой из которых будет написано отдельно.";
} else if (isNotCommentTooShort) {
error = "Недопустимо коротко комментировать длительные работы. Мы ожидаем не менее 60 символов на каждый указанный час.";
} else if (isProductiveTimeHigher) {
error = "Продуктивное время не может быть больше отработанного!";
}
} else if (!isZeroTime) {
error = "Поле комментария не может быть пустым!";
} }
let timespentValue = getTimespentValue(); const errorObj = {
error: false,
text: ""
};
if (error) {
errorObj.error = true;
errorObj.text = error;
}
dialog.style.display = "block"; return errorObj;
focusManager.capture(dialog); }
// write work time in input value window.addEventListener("load", function() {
document.querySelector("#realworktime").value = // работа с модальным окном
localStorage.time === undefined ? timespentValue : localStorage.time; const openButton = document.querySelector("#commit");
document.querySelector("#saveTime").dataset["time"] = timespentValue; const closeButton = document.querySelector("#timeQuestionDiv .close");
}); const dialog = document.querySelector("#timeQuestionDiv");
let openButtonTop = document.getElementById("commit_top"); // функция для открытия модального окна для ввода времени
function opetTimeModal(event) {
event.preventDefault();
if (openButtonTop) { closeButton.addEventListener("click", () => {
dialog.style.display = "none";
})
openButtonTop.addEventListener("click", function(event) { if (!isEtersoft()) {
// cancel form submiting const comment = document.querySelector('#comment').value.length;
event.preventDefault();
if (!isetersoft()) { if (!comment) {
const comment = document.querySelector('#comment').value.length; alert('Поле комментария не может быть пустым!');
return
}
const bugForm = isBugCreation ? "#Create" : "#changeform";
document.querySelector(bugForm).submit();
if (!comment) {
alert('Поле комментария не может быть пустым!');
return return
} }
const bugForm = etersoft_create === 1 ? "#Create" : "#changeform"; const timespentValue = getTimespentValue();
document.querySelector(bugForm).submit();
return dialog.style.display = "block";
}
let timespentValue = getTimespentValue(); focusManager.capture(dialog);
dialog.style.display = "block"; // записываем отработанное время
focusManager.capture(dialog); document.querySelector("#realworktime").value =
!localStorage.time ? timespentValue : localStorage.time;
// write work time in input value document.querySelector("#saveTime").dataset["time"] = timespentValue;
document.querySelector("#realworktime").value = }
localStorage.time === undefined ? timespentValue : localStorage.time;
document.querySelector("#saveTime").dataset["time"] = timespentValue;
});
} openButton.addEventListener("click", opetTimeModal);
document // если кнопка сохранить есть сверху, то добавим то же событие
.querySelector("#realworktime") // и на неё
.addEventListener("change", function() { const openButtonTop = document.getElementById("commit_top");
document.querySelector("#saveTime").dataset["time"] = this.value;
localStorage.time = this.value;
console.log(
"time changed:",
document.querySelector("#saveTime").dataset["time"]
);
});
document.querySelector("#realworktime").addEventListener("paste", function() { if (openButtonTop) {
document.querySelector("#saveTime").dataset["time"] = this.value; openButtonTop.addEventListener("click", opetTimeModal);
localStorage.time = this.value;
console.log(
"time changed:",
document.querySelector("#saveTime").dataset["time"]
);
});
// add listener for enter key down to work time input
document.querySelector("#realworktime").addEventListener("keyup", (event) => {
if (event.key === "Enter") {
document.querySelector("#realworktime").blur();
document.querySelector("#ProductTime").focus();
} }
});
// add listener for enter key down to productive time input function updateTimeValue() {
document.querySelector("#ProductTime").addEventListener("keyup", () => { document.querySelector("#saveTime").dataset["time"] = this.value;
if (event.key === "Enter") { localStorage.time = this.value;
document.querySelector("#saveTime").click();
} }
});
// add listener for time commit
let btn = document.querySelector("#saveTime");
btn.addEventListener("click", function(event) {
// cancel form submiting
event.preventDefault();
// let's calc time for #work_time input
let workTime = parseInt(document.querySelector("#realworktime").value);
workTime =
workTime === parseInt(btn.dataset["time"])
? parseInt(btn.dataset["time"])
: workTime;
workTime = workTime > 0 ? workTime : 0;
let workTimeValue = Math.ceil((workTime / 60) * 100) / 100;
let productiveTime = parseInt(document.querySelector("#ProductTime").value);
productiveTime = productiveTime > 0 ? productiveTime : workTime;
let productiveTimeValue = Math.ceil((productiveTime / 60) * 100) / 100;
document.querySelector("#work_time").value = workTimeValue;
document.querySelector("#productive_time").value = productiveTimeValue;
// получаем estimatedTime document
const estimatedTimeElement = document.querySelector('#estimated_time'); .querySelector("#realworktime")
const workedTimeElement = document.querySelector('.bz_time_tracking_table > tbody:nth-child(1) > tr:nth-child(2) > td:nth-child(3)'); .addEventListener("change", updateTimeValue);
if (estimatedTimeElement && workedTimeElement) { document
const estimatedTime = Number(estimatedTimeElement.value); .querySelector("#realworktime")
.addEventListener("paste", updateTimeValue);
// получаем отработанное время // add listener for enter key down to work time input
const workedTime = Number(workedTimeElement.innerText); document.querySelector("#realworktime").addEventListener("keyup", (event) => {
if (event.key === "Enter") {
document.querySelector("#realworktime").blur();
document.querySelector("#ProductTime").focus();
}
});
// пересчитанное отработанное время // add listener for enter key down to productive time input
const updatedWorkedTime = ((workedTime * 100) + (workTimeValue * 100)) / 100; document.querySelector("#ProductTime").addEventListener("keyup", () => {
if (event.key === "Enter") {
document.querySelector("#saveTime").click();
}
});
// считаем сколько осталось // add listener for time commit
const remainingTimeValue = Math.ceil(((estimatedTime * 100) - (updatedWorkedTime * 100))) / 100; const saveTimeButton = document.querySelector("#saveTime");
// обновляем оставшееся время saveTimeButton.addEventListener("click", function(event) {
document.querySelector("#remaining_time").value = remainingTimeValue > 0 ? remainingTimeValue : 0; // cancel form submiting
} event.preventDefault();
// now we ready for submiting all forms // let's calc time for #work_time input
let mainCommitBtn = document.querySelector("#commit_top"); let workTime = parseTimeInt("#realworktime");
// check comment before submit const timeFromButton = parseTimeIntFromData(saveTimeButton);
let comment = document.querySelector("#comment").value;
// если время совпадает с тем что ввёл пользователь
if (comment.length !== 0) { // будем использовать его
if (comment.length < 9) { // иначе будем использовать отработанное
alert("Слишком короткий комментарий"); workTime = workTime === timeFromButton
} else if (productiveTimeValue > 8 || workTimeValue > 8) { ? timeFromButton
alert( : workTime;
"Недопустимо указывать отработанное/продуктивное время более восьми часов. Правильным следованием рабочему процессу было бы выполнение работы по частям, о каждой из которых будет написано отдельно."
); // если время не задано, то пусть будет нулём
} else if ( workTime = workTime || 0;
productiveTimeValue > 2 &&
comment.length < productiveTimeValue * 60 const workTimeValue = calcTimeValue(workTime);
) {
alert( const productiveTime = parseTimeInt("#ProductTime") || workTime;
"Недопустимо коротко комментировать длительные работы. Мы ожидаем не менее 60 символов на каждый указанный час."
); const productiveTimeValue = calcTimeValue(productiveTime);
} else if (productiveTimeValue > workTimeValue) {
alert("Продуктивное время не может быть больше отработанного!"); document.querySelector("#work_time").value = workTimeValue;
} else { document.querySelector("#productive_time").value = productiveTimeValue;
let bugForm = etersoft_create === 1 ? "#Create" : "#changeform";
document.querySelector(bugForm).submit(); // обновим оставшееся время
timer.clear(); updateRemainingTime(workTimeValue);
localStorage.removeItem("time");
} // check comment before submit
} else if (!comment.length && workTimeValue === 0 && productiveTimeValue === 0) { const comment = document.querySelector("#comment").value;
let bugForm = etersoft_create === 1 ? "#Create" : "#changeform";
document.querySelector(bugForm).submit(); const commentData = [
timer.clear(); comment,
localStorage.removeItem("time"); workTimeValue,
} else { productiveTimeValue
alert("Поле комментария не может быть пустым!"); ];
}
}); submitComment(commentData);
});
}); });
// let's validate! // let's validate!
function validate(evt) { function validate(_event) {
let theEvent = evt || window.event; console.log(_event);
let key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key); const event = _event || window.event;
let regex = /[0-9\s]/;
if (!regex.test(key)) { console.log(event);
theEvent.returnValue = false;
if (theEvent.preventDefault) theEvent.preventDefault(); let key = event.keyCode || event.which;
}
key = String.fromCharCode(key);
const regex = /[0-9\s]/;
if (!regex.test(key)) {
event.returnValue = false;
if (event.preventDefault) event.preventDefault();
}
} }
document.querySelector("#realworktime").onkeypress = function() { function addValidationToElement(selector) {
validate(event); // добавляем слушатель на keypress
}; document
.querySelector(selector)
document.querySelector("#realworktime").onpaste = function() { .addEventListener("keypress", validate);
validate(event);
}; // добавляем слушатель на paste
document
document.querySelector("#ProductTime").onkeypress = function() { .querySelector(selector)
validate(event); .addEventListener("paste", validate);
};
document.querySelector("#ProductTime").onpaste = function() {
validate(event);
};
//////////////////////////////////////////////////////////////
if (typeof window.addEventListener != "undefined") {
//gecko, safari, konqueror and standard
window.addEventListener("load", initTimer, false);
} else if (typeof document.addEventListener != "undefined") {
//opera 7
document.addEventListener("load", initTimer, false);
} else if (typeof window.attachEvent != "undefined") {
//win/ie
window.attachEvent("onload", initTimer);
} }
addValidationToElement("#realworktime");
addValidationToElement("#ProductTime");
...@@ -39,11 +39,11 @@ ...@@ -39,11 +39,11 @@
<fieldset> <fieldset>
<button class="workTime__button--save" id="saveTime" tabindex="11">Сохранить</button> <button class="workTime__button--save" id="saveTime" tabindex="11">Сохранить</button>
</fieldset> </fieldset>
<button onclick="closeDiv();" class="close" tabindex="12">&times;</button> <button class="close" tabindex="12">&times;</button>
</div> </div>
</div> </div>
</div> </div>
<script language="javascript" type="text/javascript" src="js/etersoft/focusManager.js"></script> <script language="javascript" type="text/javascript" src="js/etersoft/focusManager.js"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer.js?24_02_2021"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer.js?22_04_2021"></script>
...@@ -39,11 +39,11 @@ ...@@ -39,11 +39,11 @@
<fieldset> <fieldset>
<button class="workTime__button--save" id="saveTime" tabindex="11">Сохранить</button> <button class="workTime__button--save" id="saveTime" tabindex="11">Сохранить</button>
</fieldset> </fieldset>
<button onclick="closeDiv();" class="close" tabindex="12">&times;</button> <button class="close" tabindex="12">&times;</button>
</div> </div>
</div> </div>
</div> </div>
<script language="javascript" type="text/javascript" src="js/etersoft/focusManager.js"></script> <script language="javascript" type="text/javascript" src="js/etersoft/focusManager.js"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer_common.js?25_10_2017"></script>
<script language="javascript" type="text/javascript" src="js/etersoft/timer.js?24_02_2021"></script> <script language="javascript" type="text/javascript" src="js/etersoft/timer.js?22_04_2021"></script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment