todos: create demo data, add some css

This commit is contained in:
muahahahh 2021-01-10 21:10:39 +01:00
parent a49c50f91e
commit 2eeda5315e
101 changed files with 1057 additions and 1375 deletions

Binary file not shown.

View File

@ -2,22 +2,23 @@
const monthsStrings = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
var today = new Date()
function addCalendar(monthsAhead = 1, currentMonth = new Date().getMonth() + 1, currentYear= new Date().getFullYear(), weekStart=1){
function addCalendar(monthsAhead , currentMonth , currentYear, weekStart, buttonEventListener){
var calendarContainer = document.createElement('div')
calendarContainer.id = 'calendar_container'
var monthsBlock = document.createElement('div')
monthsBlock.id = 'months_block'
renderCalendarFor(calendarContainer, monthsBlock, currentYear, currentMonth, monthsAhead, weekStart)
calendarContainer.appendChild(createButtonBack(calendarContainer, monthsBlock, monthsAhead, weekStart))
calendarContainer.appendChild(monthsBlock)
calendarContainer.appendChild(createButtonForwards(calendarContainer, monthsBlock, monthsAhead, weekStart))
calendarContainer.appendChild(createDateSelector(calendarContainer, monthsBlock, monthsAhead, weekStart))
var buttons = calendarContainer.getElementsByClassName('calendar_button')
for (var i = 0; i < buttons.length; i++){
buttons[i].addEventListener('click', buttonEventListener)
}
var element = calendarContainer.getElementsByTagName('button')[0]
element.addEventListener('click', buttonEventListener)
return calendarContainer
}
@ -26,7 +27,6 @@ function createButtonBack(calendarContainer, monthsBlock, monthsAhead, weekStart
buttonBack.addEventListener('click', function(){
var currentMonth = parseInt(calendarContainer.getAttribute('month_shown'))
var currentYear = parseInt(calendarContainer.getAttribute('year_shown'))
if (currentMonth == 1){
currentMonth = 12
currentYear = currentYear - 1
@ -43,7 +43,6 @@ function createButtonForwards(calendarContainer, monthsBlock, monthsAhead, weekS
buttonForwards.addEventListener('click', function(){
var currentMonth = parseInt(calendarContainer.getAttribute('month_shown'))
var currentYear = parseInt(calendarContainer.getAttribute('year_shown'))
if (currentMonth == 12){
currentMonth = 1
currentYear = currentYear + 1
@ -58,7 +57,6 @@ function createButtonForwards(calendarContainer, monthsBlock, monthsAhead, weekS
function createDateSelector(calendarContainer, monthsBlock, monthsAhead, weekStart){
var dateSelector = createDateSelectionHTML()
var buttonGoToDate = dateSelector.querySelector('#button_load_selected_months')
buttonGoToDate.addEventListener('click', function(){
var currentYear = parseInt(dateSelector.querySelector('#year_selector').value)
@ -71,7 +69,6 @@ function createDateSelector(calendarContainer, monthsBlock, monthsAhead, weekSta
function renderCalendarFor(calendarContainer, monthsBlock, year, month, nMonths, weekStart){
monthsBlock.innerHTML = ''
calendarContainer.setAttribute('month_shown', month.toString())
calendarContainer.setAttribute('year_shown', year.toString())
@ -81,12 +78,9 @@ function renderCalendarFor(calendarContainer, monthsBlock, year, month, nMonths,
if (monthToCreate == 13){
monthToCreate = 1;
year = year + 1;
// console.log(monthToCreate, month, year, nMonths)
}
var monthContainer = document.createElement('div')
monthContainer.className = 'month_container'
monthContainer.appendChild(renderMonth(year, monthToCreate, weekStart))
monthsBlock.appendChild(monthContainer)
}
@ -100,16 +94,13 @@ function renderMonth(year, month, weekStart = 0, daysOfWeekNumeric){
daysOfWeek.push(daysOfWeek.shift())
daysOfWeekNumeric.push(daysOfWeekNumeric.shift())
}
var table = document.createElement('table')
var monthString = monthsStrings[month - 1]
createHeaders(table, year, monthString, daysOfWeek)
createDates(table, year, month, daysOfWeekNumeric)
return table
}
function createHeaders(table, year, month, daysOfWeek){
let monthHeaderRow = document.createElement('tr')
let monthHeader = document.createElement('th')
@ -118,7 +109,6 @@ function createHeaders(table, year, month, daysOfWeek){
monthHeader.colSpan = 7
monthHeaderRow.appendChild(monthHeader)
table.appendChild(monthHeaderRow)
let header = document.createElement('tr')
for (var i = 0; i < daysOfWeek.length; i++){
var headerDay = document.createElement('th')
@ -133,7 +123,6 @@ function createHeaders(table, year, month, daysOfWeek){
function createDates(table, year, month, daysOfWeekNumeric){
var weekEnd = daysOfWeekNumeric[daysOfWeekNumeric.length - 1]
var daysOfMonth = daysArray(year, month, daysOfWeekNumeric)
var row = document.createElement('tr')
for (var i = 0; i < daysOfMonth.length; i++){
@ -143,11 +132,9 @@ function createDates(table, year, month, daysOfWeekNumeric){
var dateString = new Date(date.getTime() - (date.getTimezoneOffset() * 60000 ))
.toISOString()
.split("T")[0];
var dateContainer = document.createElement('div')
dateContainer.innerText = dayNr
dateContainer.className = 'days_of_month'
if (month - 1 == date.getMonth()){
dateContainer.classList.add('days_of_month_current')
dateContainer.id = 'date_' + dateString
@ -158,50 +145,36 @@ function createDates(table, year, month, daysOfWeekNumeric){
} else {
dateContainer.classList.add('days_of_month_not_current')
}
dateContainer.setAttribute('date', dateString)
cell.appendChild(dateContainer)
row.appendChild(cell)
if (date.getDay() == weekEnd) {
table.appendChild(row)
var row = document.createElement('tr')
}
}
table.appendChild(row)
}
function daysArray(year, month, daysOfWeekNumeric) {
month = month - 1
var arr = []
var daysInCurrentMonth = daysInMonth(year, month + 1)
var firstDayOfMonth = new Date(year, month, 1).getDay()
var blankDaysStart = daysOfWeekNumeric.indexOf(firstDayOfMonth) * -1
for (var i = blankDaysStart + 1; i < 1; i++){
var date = new Date(year, month, i)
arr.push(date)
}
for (var i = 1; i < daysInCurrentMonth + 1; i++){
var date = new Date(year, month, i)
arr.push(date)
}
var daysToFill = arr.length
for (var i = 1; i < 42 - daysToFill + 1; i++){
var date = new Date(year, month + 1, i)
arr.push(date)
}
return arr
}
@ -209,27 +182,21 @@ function daysInMonth (year, month) {
return new Date(year, month, 0).getDate();
}
function createDateSelectionHTML(){
var container = document.createElement('div')
container.id = 'date_selector'
var goButton = document.createElement('button')
goButton.innerText = 'Go'
goButton.id = 'button_load_selected_months'
var label = document.createElement('label')
label.setAttribute('for', 'years')
label.innerText = 'Go to: '
var selectYear = document.createElement('select')
selectYear.name='years'
selectYear.id = 'year_selector'
spanBegin = 1990
spanEnd = 2030
yearsSpan = spanEnd - spanBegin
var spanBegin = 1990
var spanEnd = 2030
var yearsSpan = spanEnd - spanBegin
for (var i = 0; i < yearsSpan; i++){
var option = document.createElement('option')
option.value = spanBegin + i
@ -237,7 +204,6 @@ function createDateSelectionHTML(){
selectYear.appendChild(option)
}
selectYear.value = today.getFullYear()
var selectMonth = document.createElement('select')
selectMonth.name='months'
selectMonth.id = 'month_selector'
@ -249,7 +215,6 @@ function createDateSelectionHTML(){
}
selectMonth.value = today.getMonth()
container.appendChild(label)
container.appendChild(selectYear)
container.appendChild(selectMonth)
@ -264,4 +229,7 @@ function createButton(id, className, innerText){
button.className = className
button.innerText = innerText
return button
}
}
export { addCalendar }

View File

@ -0,0 +1,14 @@
const urls = {
'show_schedule': {
'show': '/employee_module/show_employee_plan_api',
'update': '/employee_module/update_plan_api'
}
,
'show_timelog': {
'show': '/employee_module/show_employee_timelog_api',
'update': '/employee_module/update_timelog_api',
}
}
export { urls }

View File

@ -0,0 +1,30 @@
import { addCalendar } from './calendar.js';
import { appendLegend, formatCalendarContainerSize, formatCalendarSize} from "./calendar_extended.js";
import { fetchDays } from './calendar_ajax_employee_module_requests.js'
window.addEventListener('load', renderWhole)
function renderWhole(){
var parent = document.getElementById('calendar_box')
parent.innerHTML = ''
parent.appendChild(addCalendar(3, new Date().getMonth() + 1, new Date().getFullYear(), 1, fetchDays))
appendLegend()
formatCalendarContainerSize(document.getElementById('calendar_container'))
formatCalendarSize()
console.log('hoba')
fetchDays()
}
export { renderWhole }

View File

@ -0,0 +1,68 @@
import {addClassToWorkingDays, searchedDateRange} from "./calendar_extended.js";
import {csrftoken} from "../../../static/js/csrf_token.js";
import {detailedRecordsMainBlock, formatTableSize} from "./calendar_employee_module_to_table.js";
import { urls } from './calendar_ajax_employee_module_config.js'
function fetchDays(){
var host = 'http://' + window.location.host;
var fetch_url = host + urls[window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1)]['show']
var range = searchedDateRange()
var startDate = range['min']
var endDate = range['max']
var username = document.getElementById('username_input').value
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"username": username,
"start_date": startDate,
"end_date" : endDate
}),
}).then((response) => {
return response.json();
}).then((data) => {
addClassToWorkingDays(data);
var parent = document.getElementById('hr_module_main_container')
var listContainer = document.getElementById('list_container')
if (listContainer == null){
var listContainer = document.createElement('div')
listContainer.id = 'list_container'
} else {
listContainer.innerHTML = ''
}
listContainer.appendChild(detailedRecordsMainBlock(data))
parent.appendChild(listContainer)
formatTableSize()
});
}
function updateCheckedRecords(recordsArray, action){
var host = 'http://' + window.location.host;
var fetch_url = host + urls[window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1)]['update']
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
'action': action,
'records': recordsArray,
}),
}).then((response) => {
return response.json();
}).then((data) => {
fetchDays()
})
}
export { fetchDays, updateCheckedRecords }

View File

@ -0,0 +1,68 @@
import { updateCheckedRecords } from './calendar_ajax_employee_module_requests.js'
function detailedRecordsMainBlock(data){
var container = document.createElement('div')
var buttonsContainer = document.createElement('div')
buttonsContainer.id = 'buttons_container'
container.appendChild(detailedCalendarRecordsTable(data))
return container
}
function detailedCalendarRecordsTable(data){
var table = createDetailedHeaders()
for (var i = 0; i < data.length; i++){
var index = data[i]['id']
var username = data[i]['username_id']
var row = table.insertRow(-1)
row.id = 'database_id_' + index.toString()
row.className = 'database_row'
row.setAttribute('database_username', username)
appendCell(row, 'div', 'date', data[i]['date'], 0)
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
}
return table
}
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
var cell = tableRow.insertCell(cellIndex)
var textInput = document.createElement(tag)
textInput.innerText = tagText
textInput.name = tagName
textInput.className = tagName
cell.appendChild(textInput)
}
function formatTableSize(){
var calendar = document.getElementById('calendar_container')
var tableDiv = document.getElementById('list_container')
var width = calendar.offsetWidth
tableDiv.setAttribute('style', 'width:' + width + 'px')
}
function createDetailedHeaders(){
var table = document.createElement('table')
let headerRow = document.createElement('tr')
let columns = ['Date', 'Start time', 'End time', 'Activity type']
for (let i = 0; i < columns.length; i++){
var headerCell = document.createElement('th')
var headerText = document.createElement('div')
headerText.innerText = columns[i]
headerCell.appendChild(headerText)
headerRow.appendChild(headerCell)
}
table.appendChild(headerRow)
table.id = 'detailed_plan_records'
return table
}
export { detailedRecordsMainBlock, formatTableSize }

View File

@ -0,0 +1,91 @@
function appendLegend(){
var calendar = document.getElementById('calendar_container')
var container = document.createElement('div')
container.id = 'legend_container'
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
for(var i = 0; i < activityTypes.length; i++){
var legendElementContainer = document.createElement('div')
legendElementContainer.className = 'legend_element_container'
var legendDivText = document.createElement('div')
legendDivText.innerText = activityTypes[i]
legendDivText.className = 'legend_label'
var legendDivBox = document.createElement('div')
legendDivBox.classList.add('legend_cube')
legendDivBox.classList.add('days_of_month_' + activityTypes[i])
legendElementContainer.appendChild(legendDivText)
legendElementContainer.appendChild(legendDivBox)
container.appendChild(legendElementContainer)
}
calendar.appendChild(container)
}
function formatCalendarContainerSize(calendarContainer){
var monthsBlock = calendarContainer.querySelector('#months_block')
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
var dateSelector = calendarContainer.querySelector('#date_selector')
var legendSelector = calendarContainer.querySelector('#legend_container')
var widthMonths = monthsBlock.offsetWidth
var heightMonths = monthsBlock.offsetHeight
var heightDateSelector = dateSelector.offsetHeight
var heightLegend = legendSelector.offsetHeight
var widthCalendarButton = calendarButton.offsetWidth * 2
var widthTotal = widthMonths + widthCalendarButton
var heightTotal = heightMonths + heightDateSelector + heightLegend
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
}
function formatCalendarSize(){
var calendarBox = document.getElementById('calendar_box')
var calendar = document.getElementById('calendar_container')
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
}
function cleanCalendarClasses(){
var classesToKeep = ['days_of_month', 'days_of_month_current', 'days_of_month_today']
var days = document.getElementsByClassName('days_of_month_current')
for (var i = 0; i < days.length; i++){
var classList = days[i].classList
for (var j = 0; j < classList.length; j++){
if (!classesToKeep.includes(classList[j])){
days[i].classList.remove(classList[j])
console.log('removed ' + classList[j])
}
}
}
}
function addClassToWorkingDays(data){
cleanCalendarClasses()
for (var i = 0; i < data.length; i++){
var processedDate = data[i]['date']
var processedActivityType = data[i]['activity_type']
var nodeToChange = document.getElementById('date_' + processedDate)
nodeToChange.classList.add('days_of_month_' + processedActivityType)
}
}
function searchedDateRange(){
var dates = document.getElementsByClassName('days_of_month_current')
var datesArray = []
for (var i = 0; i < dates.length; i++){
var dateAttr = new Date(dates[i].getAttribute('date'))
datesArray.push(dateAttr)
}
var minDate = new Date(Math.min.apply(null, datesArray))
var maxDate = new Date(Math.max.apply(null, datesArray))
var out = {'min' : minDate,
'max': maxDate}
console.log(out)
return out
}
export { appendLegend, formatCalendarContainerSize, formatCalendarSize, addClassToWorkingDays, searchedDateRange }

View File

@ -0,0 +1,62 @@
import {csrftoken} from "../../../static/js/csrf_token.js";
var searchEmployeeButton = document.getElementById('load_employee_data_button')
searchEmployeeButton.addEventListener('click', function(){
fetchSearchEmployeeData()
})
function fetchSearchEmployeeData() {
var host = 'http://' + window.location.host;
var fetch_url = host + '/hr_module/change_employee_data_api'
var username = document.getElementById('username_input').value
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"username": username
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
loadValuesIntoPage(data)
});
}
function loadValuesIntoPage(data){
var order = ['username', 'first_name', 'last_name', 'email', 'department', 'manager_username', 'time_model_id', 'manager_flag', 'is_active', 'is_staff', 'is_superuser']
var informationContainer = document.getElementById('search_results')
for (var i = 0; i < order.length; i++){
var field = order[i]
var value = data[field]
var fieldContainer = document.createElement('div')
fieldContainer.className = 'field_container'
if (typeof(value) === 'boolean'){
var httpfield = document.createElement('input')
httpfield.type = 'checkbox'
httpfield.checked = value
httpfield.setAttribute('disabled', 'disabled')
} else {
var httpfield = document.createElement('div')
httpfield.innerHTML = value
}
var label = document.createElement('label')
label.setAttribute('for', field)
label.innerText = field.replace('_', ' ')
httpfield.id = field
httpfield.className = 'database_field'
fieldContainer.appendChild(label)
fieldContainer.appendChild(httpfield)
informationContainer.appendChild(fieldContainer)
}
}

View File

@ -1,4 +1,4 @@
const csrftoken = getCookie('csrftoken');
import {csrftoken} from "../../../static/js/csrf_token.js";
window.addEventListener('load', function(){
fetchSearchEmployeeData()

View File

@ -1,201 +0,0 @@
const csrftoken = getCookie('csrftoken');
// document.onload = parent.appendChild(addCalendar(monthsAhead=3))
window.addEventListener('load', function(){
var parent = document.getElementById('calendar_box')
parent.appendChild(addCalendar(monthsAhead=3))
appendLegend()
fetchDays()
formatCalendarContainerSize(document.getElementById('calendar_container'))
document.getElementById('calendar_button_back').addEventListener('click', function(){
fetchDays()
})
document.getElementById('calendar_button_forwards').addEventListener('click', function(){
fetchDays()
})
document.getElementById('button_load_selected_months').addEventListener('click', function(){
fetchDays()
})
})
function fetchDays(){
var host = 'http://' + window.location.host;
var fetch_url = host + '/employee_module/show_employee_plan_api'
var range = searchedDateRange()
var startDate = range['min']
var endDate = range['max']
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"start_date": startDate,
"end_date" : endDate
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
addClassToWorkingDays(data);
var parent = document.getElementById('hr_module_main_container')
var listContainer = document.getElementById('list_container')
if (listContainer == null){
var listContainer = document.createElement('div')
listContainer.id = 'list_container'
} else {
listContainer.innerHTML = ''
}
listContainer.appendChild(createDetailedCalendarRecords(data))
parent.appendChild(listContainer)
formatTableSize()
});
}
function addClassToWorkingDays(data){
for (var i = 0; i < data.length; i++){
var processedDate = data[i]['date']
var processedActivityType = data[i]['activity_type']
var nodeToChange = document.getElementById('date_' + processedDate)
nodeToChange.classList.add('days_of_month_' + processedActivityType)
}
}
function createDetailedCalendarRecords(data){
var table = createDetailedHeaders()
for (var i = 0; i < data.length; i++){
var index = data[i]['id']
var username = data[i]['username_id']
var row = table.insertRow(-1)
row.id = 'database_id_' + index.toString()
row.setAttribute('database_username', username)
appendCell(row, 'div', 'date', data[i]['date'], 0)
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
}
return table
}
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
var cell = tableRow.insertCell(cellIndex)
var textInput = document.createElement(tag)
textInput.innerText = tagText
textInput.name = tagName
cell.appendChild(textInput)
}
function createDetailedHeaders(){
var table = document.createElement('table')
let headerRow = document.createElement('tr')
let columns = ['Date', 'Start time', 'End time', 'Activity type']
for (let i = 0; i < columns.length; i++){
var headerCell = document.createElement('th')
var headerText = document.createElement('div')
headerText.innerText = columns[i]
headerCell.appendChild(headerText)
headerRow.appendChild(headerCell)
}
table.appendChild(headerRow)
table.id = 'detailed_plan_records'
return table
}
function formatCalendarContainerSize(calendarContainer){
var monthsBlock = calendarContainer.querySelector('#months_block')
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
var dateSelector = calendarContainer.querySelector('#date_selector')
var legendSelector = calendarContainer.querySelector('#legend_container')
var widthMonths = monthsBlock.offsetWidth
var heightMonths = monthsBlock.offsetHeight
var heightDateSelector = dateSelector.offsetHeight
var heightLegend = legendSelector.offsetHeight
var widthCalendarButton = calendarButton.offsetWidth * 2
var widthTotal = widthMonths + widthCalendarButton
var heightTotal = heightMonths + heightDateSelector + heightLegend
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
}
function formatTableSize(){
var calendarBox = document.getElementById('calendar_box')
var calendar = document.getElementById('calendar_container')
var tableDiv = document.getElementById('list_container')
var width = calendar.offsetWidth
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
tableDiv.setAttribute('style', 'width:' + width + 'px')
}
function searchedDateRange(){
var dates = document.getElementsByClassName('days_of_month_current')
var datesArray = []
for (var i = 0; i < dates.length; i++){
var dateAttr = new Date(dates[i].getAttribute('date'))
datesArray.push(dateAttr)
}
var minDate = new Date(Math.min.apply(null, datesArray))
var maxDate = new Date(Math.max.apply(null, datesArray))
var out = {'min' : minDate,
'max': maxDate}
console.log(out)
return out
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function appendLegend(){
var calendar = document.getElementById('calendar_container')
var container = document.createElement('div')
container.id = 'legend_container'
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
for(var i = 0; i < activityTypes.length; i++){
var legendElementContainer = document.createElement('div')
legendElementContainer.className = 'legend_element_container'
var legendDivText = document.createElement('div')
legendDivText.innerText = activityTypes[i]
legendDivText.className = 'legend_label'
var legendDivBox = document.createElement('div')
legendDivBox.classList.add('legend_cube')
legendDivBox.classList.add('days_of_month_' + activityTypes[i])
legendElementContainer.appendChild(legendDivText)
legendElementContainer.appendChild(legendDivBox)
container.appendChild(legendElementContainer)
}
calendar.appendChild(container)
}

View File

@ -1,201 +0,0 @@
const csrftoken = getCookie('csrftoken');
// document.onload = parent.appendChild(addCalendar(monthsAhead=3))
window.addEventListener('load', function(){
var parent = document.getElementById('calendar_box')
parent.appendChild(addCalendar(monthsAhead=3))
appendLegend()
fetchDays()
formatCalendarContainerSize(document.getElementById('calendar_container'))
document.getElementById('calendar_button_back').addEventListener('click', function(){
fetchDays()
})
document.getElementById('calendar_button_forwards').addEventListener('click', function(){
fetchDays()
})
document.getElementById('button_load_selected_months').addEventListener('click', function(){
fetchDays()
})
})
function fetchDays(){
var host = 'http://' + window.location.host;
var fetch_url = host + '/employee_module/show_employee_timelog_api'
var range = searchedDateRange()
var startDate = range['min']
var endDate = range['max']
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"start_date": startDate,
"end_date" : endDate
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
addClassToWorkingDays(data);
var parent = document.getElementById('hr_module_main_container')
var listContainer = document.getElementById('list_container')
if (listContainer == null){
var listContainer = document.createElement('div')
listContainer.id = 'list_container'
} else {
listContainer.innerHTML = ''
}
listContainer.appendChild(createDetailedCalendarRecords(data))
parent.appendChild(listContainer)
formatTableSize()
});
}
function addClassToWorkingDays(data){
for (var i = 0; i < data.length; i++){
var processedDate = data[i]['date']
var processedActivityType = data[i]['activity_type']
var nodeToChange = document.getElementById('date_' + processedDate)
nodeToChange.classList.add('days_of_month_' + processedActivityType)
}
}
function createDetailedCalendarRecords(data){
var table = createDetailedHeaders()
for (var i = 0; i < data.length; i++){
var index = data[i]['id']
var username = data[i]['username_id']
var row = table.insertRow(-1)
row.id = 'database_id_' + index.toString()
row.setAttribute('database_username', username)
appendCell(row, 'div', 'date', data[i]['date'], 0)
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
}
return table
}
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
var cell = tableRow.insertCell(cellIndex)
var textInput = document.createElement(tag)
textInput.innerText = tagText
textInput.name = tagName
cell.appendChild(textInput)
}
function createDetailedHeaders(){
var table = document.createElement('table')
let headerRow = document.createElement('tr')
let columns = ['Date', 'Start time', 'End time', 'Activity type']
for (let i = 0; i < columns.length; i++){
var headerCell = document.createElement('th')
var headerText = document.createElement('div')
headerText.innerText = columns[i]
headerCell.appendChild(headerText)
headerRow.appendChild(headerCell)
}
table.appendChild(headerRow)
table.id = 'detailed_plan_records'
return table
}
function formatCalendarContainerSize(calendarContainer){
var monthsBlock = calendarContainer.querySelector('#months_block')
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
var dateSelector = calendarContainer.querySelector('#date_selector')
var legendSelector = calendarContainer.querySelector('#legend_container')
var widthMonths = monthsBlock.offsetWidth
var heightMonths = monthsBlock.offsetHeight
var heightDateSelector = dateSelector.offsetHeight
var heightLegend = legendSelector.offsetHeight
var widthCalendarButton = calendarButton.offsetWidth * 2
var widthTotal = widthMonths + widthCalendarButton
var heightTotal = heightMonths + heightDateSelector + heightLegend
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
}
function formatTableSize(){
var calendarBox = document.getElementById('calendar_box')
var calendar = document.getElementById('calendar_container')
var tableDiv = document.getElementById('list_container')
var width = calendar.offsetWidth
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
tableDiv.setAttribute('style', 'width:' + width + 'px')
}
function searchedDateRange(){
var dates = document.getElementsByClassName('days_of_month_current')
var datesArray = []
for (var i = 0; i < dates.length; i++){
var dateAttr = new Date(dates[i].getAttribute('date'))
datesArray.push(dateAttr)
}
var minDate = new Date(Math.min.apply(null, datesArray))
var maxDate = new Date(Math.max.apply(null, datesArray))
var out = {'min' : minDate,
'max': maxDate}
console.log(out)
return out
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function appendLegend(){
var calendar = document.getElementById('calendar_container')
var container = document.createElement('div')
container.id = 'legend_container'
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
for(var i = 0; i < activityTypes.length; i++){
var legendElementContainer = document.createElement('div')
legendElementContainer.className = 'legend_element_container'
var legendDivText = document.createElement('div')
legendDivText.innerText = activityTypes[i]
legendDivText.className = 'legend_label'
var legendDivBox = document.createElement('div')
legendDivBox.classList.add('legend_cube')
legendDivBox.classList.add('days_of_month_' + activityTypes[i])
legendElementContainer.appendChild(legendDivText)
legendElementContainer.appendChild(legendDivBox)
container.appendChild(legendElementContainer)
}
calendar.appendChild(container)
}

View File

@ -8,7 +8,6 @@
{% block core_content %}
<script src="{% static '/js/csrf_token.js' %}"></script>
<div id="sidebar">
@ -37,6 +36,14 @@
</div>
</a>
{% if request.user.is_superuser or MANAGER_FLAG %}
<a href="{% url 'hr_module:homepage' %}">
<div class="sidebar_item">Go to administration site
</div>
</a>
{% endif %}
</div>
<div id="hr_module_main_container">

View File

@ -10,6 +10,6 @@
</div>
<script src="{% static '/js/employee_module_show_employee_data.js' %}"></script>
<script type="module" src="{% static '/js/employee_module_show_employee_data.js' %}"></script>
{% endblock %}

View File

@ -7,13 +7,13 @@
<link rel="stylesheet" href="{% static '/css/calendar_local.css' %}">
<link rel="stylesheet" href="{% static '/css/employee_module_show_schedule.css' %}">
<div>
<div id="username" username="{{ user }}"></div>
<div hidden>
<div id="username_input" username="{{ user }}"></div>
<button type="button" id="load_schedule_button">Load Schedule</button>
</div>
<div id="calendar_box"></div>
<script src="{% static '/js/calendar.js' %}"></script>
<script src="{% static '/js/employee_module_show_schedule.js' %}"></script>
<script type="module" src="{% static '/js/calendar_ajax_employee_module_main.js' %}"></script>
{% endblock %}

View File

@ -7,13 +7,12 @@
<link rel="stylesheet" href="{% static '/css/calendar_local.css' %}">
<link rel="stylesheet" href="{% static '/css/employee_module_show_schedule.css' %}">
<div>
<div id="username" username="{{ user }}"></div>
<div hidden>
<div id="username_input" username="{{ user }}"></div>
<button type="button" id="load_schedule_button">Load Schedule</button>
</div>
<div id="calendar_box"></div>
<script src="{% static '/js/calendar.js' %}"></script>
<script src="{% static '/js/employee_module_show_timelog.js' %}"></script>
<script type="module" src="{% static '/js/calendar_ajax_employee_module_main.js' %}"></script>
{% endblock %}

View File

@ -6,9 +6,6 @@ from django.contrib.auth import views as auth_views
app_name = 'employee_module'
urlpatterns = [
path('login', auth_views.LoginView.as_view(template_name='hr_module_login.html'), name='login'),
path('logout', auth_views.LogoutView.as_view(), name='logout'),
path('change_password', auth_views.PasswordChangeView.as_view(template_name='hr_module_password_change.html'), name='change_password'),
path('home', views.homepage, name='homepage'),
path('time_tracking', views.time_tracking, name='time_tracking'),
path('show_schedule', views.show_schedule, name='show_schedule'),

View File

@ -5,11 +5,11 @@ from hr_module.models import Employee, Plan, TimeLog
from django.contrib.auth.models import User
from django.http import HttpResponse, JsonResponse, Http404
import datetime
from django.urls import reverse
from django.urls import reverse, reverse_lazy
from django.http import HttpResponse, HttpResponseRedirect
login_url = '/hr_module/login'
login_url = reverse_lazy('login')
# Create your views here.
@login_required(login_url=login_url)
def homepage(request):

Binary file not shown.

View File

@ -1,5 +1,10 @@
from django.conf import settings
from django.contrib.auth.models import User
def report_download_path(request):
return {'IMPORT_REPORT_STORAGE': settings.IMPORT_REPORT_STORAGE}
def manager_flag(request):
if request.user.is_authenticated:
session_user = User.objects.select_related('employee').get(username=request.user.username)
manager_flag = session_user.employee.manager_flag
else:
manager_flag = None
return {'MANAGER_FLAG': manager_flag}

View File

@ -88,4 +88,4 @@ def create_planning_operation_report(dict_, current_user):
filename = current_user + '_' + datetime.datetime.now().isoformat() + '.xlsx'
path_temp = settings.IMPORT_REPORT_STORAGE + filename
df.to_excel(path_temp, index=False)
return filename
return filename

47
hr_module/sql_queries.py Normal file
View File

@ -0,0 +1,47 @@
export_query_body = '''select d.username,
d.first_name,
d.last_name,
d.manager_username,
d.department,
c.month,
c.activity_type,
c.time_should,
c.time_is,
c.overtime as difference_hours
from (select *
from auth_user a
inner join hr_module_employee b on a.username = b.username) d
left join (
select plan.username_id,
plan.month,
plan.activity_type,
plan.time_should,
log.time_is,
log.time_is - plan.time_should as overtime
from (
select username_id,
activity_type,
strftime('%Y-%m') as month,
sum(strftime('%s', end_time) - strftime('%s', begin_time)) / 3600 as time_should
from hr_module_plan
group by username_id, activity_type, strftime('%Y-%m')
) plan
left join (
select username_id,
activity_type,
strftime('%Y-%m') as month,
sum(strftime('%s', end_time) - strftime('%s', begin_time)) / 3600 as time_is
from hr_module_timelog
group by username_id, activity_type, strftime('%Y-%m')
) log on log.username_id = plan.username_id and log.activity_type = plan.activity_type and
log.month = plan.month
) c on c.username_id = d.username
where c.month in {} '''
export_queries = {'username': export_query_body + "and d.username = '{}'",
'department': export_query_body + "and d.department = '{}'",
'manager': export_query_body + "and d.manager_username = '{}'"}

View File

@ -5,7 +5,7 @@ input[readonly] {
}
table#detailed_plan_records {
margin-top: 15px;
margin-top: 10px;
width: 100%;
font-size: 15px;
vertical-align:middle;
@ -42,4 +42,21 @@ div#detailed_plan_records input {
.begin_time, .end_time {
display: block;
}
#list_container {
margin-top: 20px;
}
#buttons_container {
margin-left: 2px;
}
#buttons_container button {
width: 157px;
margin-right: 10px;
}
#checkox_select_button {
margin-right: 0px;
}

View File

@ -5,6 +5,7 @@ input[readonly] {
}
table#detailed_plan_records {
margin-top: 10px;
width: 100%;
font-size: 15px;
vertical-align:middle;
@ -41,4 +42,22 @@ div#detailed_plan_records input {
.begin_time, .end_time {
display: block;
}
#list_container {
margin-top: 20px;
}
#buttons_container {
margin-left: 2px;
}
#buttons_container button {
width: 157px;
margin-right: 10px;
}
#checkox_select_button {
margin-right: 0px;
}

View File

@ -2,22 +2,23 @@
const monthsStrings = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
var today = new Date()
function addCalendar(monthsAhead = 1, currentMonth = new Date().getMonth() + 1, currentYear= new Date().getFullYear(), weekStart=1){
function addCalendar(monthsAhead , currentMonth , currentYear, weekStart, buttonEventListener){
var calendarContainer = document.createElement('div')
calendarContainer.id = 'calendar_container'
var monthsBlock = document.createElement('div')
monthsBlock.id = 'months_block'
renderCalendarFor(calendarContainer, monthsBlock, currentYear, currentMonth, monthsAhead, weekStart)
calendarContainer.appendChild(createButtonBack(calendarContainer, monthsBlock, monthsAhead, weekStart))
calendarContainer.appendChild(monthsBlock)
calendarContainer.appendChild(createButtonForwards(calendarContainer, monthsBlock, monthsAhead, weekStart))
calendarContainer.appendChild(createDateSelector(calendarContainer, monthsBlock, monthsAhead, weekStart))
var buttons = calendarContainer.getElementsByClassName('calendar_button')
for (var i = 0; i < buttons.length; i++){
buttons[i].addEventListener('click', buttonEventListener)
}
var element = calendarContainer.getElementsByTagName('button')[0]
element.addEventListener('click', buttonEventListener)
return calendarContainer
}
@ -26,7 +27,6 @@ function createButtonBack(calendarContainer, monthsBlock, monthsAhead, weekStart
buttonBack.addEventListener('click', function(){
var currentMonth = parseInt(calendarContainer.getAttribute('month_shown'))
var currentYear = parseInt(calendarContainer.getAttribute('year_shown'))
if (currentMonth == 1){
currentMonth = 12
currentYear = currentYear - 1
@ -43,7 +43,6 @@ function createButtonForwards(calendarContainer, monthsBlock, monthsAhead, weekS
buttonForwards.addEventListener('click', function(){
var currentMonth = parseInt(calendarContainer.getAttribute('month_shown'))
var currentYear = parseInt(calendarContainer.getAttribute('year_shown'))
if (currentMonth == 12){
currentMonth = 1
currentYear = currentYear + 1
@ -58,7 +57,6 @@ function createButtonForwards(calendarContainer, monthsBlock, monthsAhead, weekS
function createDateSelector(calendarContainer, monthsBlock, monthsAhead, weekStart){
var dateSelector = createDateSelectionHTML()
var buttonGoToDate = dateSelector.querySelector('#button_load_selected_months')
buttonGoToDate.addEventListener('click', function(){
var currentYear = parseInt(dateSelector.querySelector('#year_selector').value)
@ -71,7 +69,6 @@ function createDateSelector(calendarContainer, monthsBlock, monthsAhead, weekSta
function renderCalendarFor(calendarContainer, monthsBlock, year, month, nMonths, weekStart){
monthsBlock.innerHTML = ''
calendarContainer.setAttribute('month_shown', month.toString())
calendarContainer.setAttribute('year_shown', year.toString())
@ -81,12 +78,9 @@ function renderCalendarFor(calendarContainer, monthsBlock, year, month, nMonths,
if (monthToCreate == 13){
monthToCreate = 1;
year = year + 1;
// console.log(monthToCreate, month, year, nMonths)
}
var monthContainer = document.createElement('div')
monthContainer.className = 'month_container'
monthContainer.appendChild(renderMonth(year, monthToCreate, weekStart))
monthsBlock.appendChild(monthContainer)
}
@ -100,16 +94,13 @@ function renderMonth(year, month, weekStart = 0, daysOfWeekNumeric){
daysOfWeek.push(daysOfWeek.shift())
daysOfWeekNumeric.push(daysOfWeekNumeric.shift())
}
var table = document.createElement('table')
var monthString = monthsStrings[month - 1]
createHeaders(table, year, monthString, daysOfWeek)
createDates(table, year, month, daysOfWeekNumeric)
return table
}
function createHeaders(table, year, month, daysOfWeek){
let monthHeaderRow = document.createElement('tr')
let monthHeader = document.createElement('th')
@ -118,7 +109,6 @@ function createHeaders(table, year, month, daysOfWeek){
monthHeader.colSpan = 7
monthHeaderRow.appendChild(monthHeader)
table.appendChild(monthHeaderRow)
let header = document.createElement('tr')
for (var i = 0; i < daysOfWeek.length; i++){
var headerDay = document.createElement('th')
@ -133,7 +123,6 @@ function createHeaders(table, year, month, daysOfWeek){
function createDates(table, year, month, daysOfWeekNumeric){
var weekEnd = daysOfWeekNumeric[daysOfWeekNumeric.length - 1]
var daysOfMonth = daysArray(year, month, daysOfWeekNumeric)
var row = document.createElement('tr')
for (var i = 0; i < daysOfMonth.length; i++){
@ -143,11 +132,9 @@ function createDates(table, year, month, daysOfWeekNumeric){
var dateString = new Date(date.getTime() - (date.getTimezoneOffset() * 60000 ))
.toISOString()
.split("T")[0];
var dateContainer = document.createElement('div')
dateContainer.innerText = dayNr
dateContainer.className = 'days_of_month'
if (month - 1 == date.getMonth()){
dateContainer.classList.add('days_of_month_current')
dateContainer.id = 'date_' + dateString
@ -158,50 +145,36 @@ function createDates(table, year, month, daysOfWeekNumeric){
} else {
dateContainer.classList.add('days_of_month_not_current')
}
dateContainer.setAttribute('date', dateString)
cell.appendChild(dateContainer)
row.appendChild(cell)
if (date.getDay() == weekEnd) {
table.appendChild(row)
var row = document.createElement('tr')
}
}
table.appendChild(row)
}
function daysArray(year, month, daysOfWeekNumeric) {
month = month - 1
var arr = []
var daysInCurrentMonth = daysInMonth(year, month + 1)
var firstDayOfMonth = new Date(year, month, 1).getDay()
var blankDaysStart = daysOfWeekNumeric.indexOf(firstDayOfMonth) * -1
for (var i = blankDaysStart + 1; i < 1; i++){
var date = new Date(year, month, i)
arr.push(date)
}
for (var i = 1; i < daysInCurrentMonth + 1; i++){
var date = new Date(year, month, i)
arr.push(date)
}
var daysToFill = arr.length
for (var i = 1; i < 42 - daysToFill + 1; i++){
var date = new Date(year, month + 1, i)
arr.push(date)
}
return arr
}
@ -209,27 +182,21 @@ function daysInMonth (year, month) {
return new Date(year, month, 0).getDate();
}
function createDateSelectionHTML(){
var container = document.createElement('div')
container.id = 'date_selector'
var goButton = document.createElement('button')
goButton.innerText = 'Go'
goButton.id = 'button_load_selected_months'
var label = document.createElement('label')
label.setAttribute('for', 'years')
label.innerText = 'Go to: '
var selectYear = document.createElement('select')
selectYear.name='years'
selectYear.id = 'year_selector'
spanBegin = 1990
spanEnd = 2030
yearsSpan = spanEnd - spanBegin
var spanBegin = 1990
var spanEnd = 2030
var yearsSpan = spanEnd - spanBegin
for (var i = 0; i < yearsSpan; i++){
var option = document.createElement('option')
option.value = spanBegin + i
@ -237,7 +204,6 @@ function createDateSelectionHTML(){
selectYear.appendChild(option)
}
selectYear.value = today.getFullYear()
var selectMonth = document.createElement('select')
selectMonth.name='months'
selectMonth.id = 'month_selector'
@ -249,7 +215,6 @@ function createDateSelectionHTML(){
}
selectMonth.value = today.getMonth()
container.appendChild(label)
container.appendChild(selectYear)
container.appendChild(selectMonth)
@ -264,4 +229,7 @@ function createButton(id, className, innerText){
button.className = className
button.innerText = innerText
return button
}
}
export { addCalendar }

View File

@ -0,0 +1,14 @@
const urls = {
'show_schedule': {
'show': '/hr_module/show_employee_plan_api',
'update': '/hr_module/update_plan_api'
}
,
'show_timelog': {
'show': '/hr_module/show_employee_timelog_api',
'update': '/hr_module/update_timelog_api',
}
}
export { urls }

View File

@ -0,0 +1,31 @@
import { addCalendar } from './calendar.js';
import { appendLegend, formatCalendarContainerSize, formatCalendarSize} from "./calendar_extended.js";
import { fetchDays } from './calendar_ajax_hr_module_requests.js'
window.addEventListener('load', renderWhole)
function renderWhole(){
var parent = document.getElementById('calendar_box')
parent.innerHTML = ''
parent.appendChild(addCalendar(3, new Date().getMonth() + 1, new Date().getFullYear(), 1, fetchDays))
appendLegend()
formatCalendarContainerSize(document.getElementById('calendar_container'))
formatCalendarSize()
document.getElementById('load_schedule_button').addEventListener('click', function(){
fetchDays()
})
}
export { renderWhole }

View File

@ -0,0 +1,68 @@
import {addClassToWorkingDays, searchedDateRange} from "./calendar_extended.js";
import {csrftoken} from "../../../static/js/csrf_token.js";
import {detailedRecordsMainBlock, formatTableSize} from "./calendar_to_table.js";
import { urls } from './calendar_ajax_hr_module_config.js'
function fetchDays(){
var host = 'http://' + window.location.host;
var fetch_url = host + urls[window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1)]['show']
var range = searchedDateRange()
var startDate = range['min']
var endDate = range['max']
var username = document.getElementById('username_input').value
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"username": username,
"start_date": startDate,
"end_date" : endDate
}),
}).then((response) => {
return response.json();
}).then((data) => {
addClassToWorkingDays(data);
var parent = document.getElementById('hr_module_main_container')
var listContainer = document.getElementById('list_container')
if (listContainer == null){
var listContainer = document.createElement('div')
listContainer.id = 'list_container'
} else {
listContainer.innerHTML = ''
}
listContainer.appendChild(detailedRecordsMainBlock(data))
parent.appendChild(listContainer)
formatTableSize()
});
}
function updateCheckedRecords(recordsArray, action){
var host = 'http://' + window.location.host;
var fetch_url = host + urls[window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1)]['update']
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
'action': action,
'records': recordsArray,
}),
}).then((response) => {
return response.json();
}).then((data) => {
fetchDays()
})
}
export { fetchDays, updateCheckedRecords }

View File

@ -0,0 +1,91 @@
function appendLegend(){
var calendar = document.getElementById('calendar_container')
var container = document.createElement('div')
container.id = 'legend_container'
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
for(var i = 0; i < activityTypes.length; i++){
var legendElementContainer = document.createElement('div')
legendElementContainer.className = 'legend_element_container'
var legendDivText = document.createElement('div')
legendDivText.innerText = activityTypes[i]
legendDivText.className = 'legend_label'
var legendDivBox = document.createElement('div')
legendDivBox.classList.add('legend_cube')
legendDivBox.classList.add('days_of_month_' + activityTypes[i])
legendElementContainer.appendChild(legendDivText)
legendElementContainer.appendChild(legendDivBox)
container.appendChild(legendElementContainer)
}
calendar.appendChild(container)
}
function formatCalendarContainerSize(calendarContainer){
var monthsBlock = calendarContainer.querySelector('#months_block')
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
var dateSelector = calendarContainer.querySelector('#date_selector')
var legendSelector = calendarContainer.querySelector('#legend_container')
var widthMonths = monthsBlock.offsetWidth
var heightMonths = monthsBlock.offsetHeight
var heightDateSelector = dateSelector.offsetHeight
var heightLegend = legendSelector.offsetHeight
var widthCalendarButton = calendarButton.offsetWidth * 2
var widthTotal = widthMonths + widthCalendarButton
var heightTotal = heightMonths + heightDateSelector + heightLegend
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
}
function formatCalendarSize(){
var calendarBox = document.getElementById('calendar_box')
var calendar = document.getElementById('calendar_container')
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
}
function cleanCalendarClasses(){
var classesToKeep = ['days_of_month', 'days_of_month_current', 'days_of_month_today']
var days = document.getElementsByClassName('days_of_month_current')
for (var i = 0; i < days.length; i++){
var classList = days[i].classList
for (var j = 0; j < classList.length; j++){
if (!classesToKeep.includes(classList[j])){
days[i].classList.remove(classList[j])
console.log('removed ' + classList[j])
}
}
}
}
function addClassToWorkingDays(data){
cleanCalendarClasses()
for (var i = 0; i < data.length; i++){
var processedDate = data[i]['date']
var processedActivityType = data[i]['activity_type']
var nodeToChange = document.getElementById('date_' + processedDate)
nodeToChange.classList.add('days_of_month_' + processedActivityType)
}
}
function searchedDateRange(){
var dates = document.getElementsByClassName('days_of_month_current')
var datesArray = []
for (var i = 0; i < dates.length; i++){
var dateAttr = new Date(dates[i].getAttribute('date'))
datesArray.push(dateAttr)
}
var minDate = new Date(Math.min.apply(null, datesArray))
var maxDate = new Date(Math.max.apply(null, datesArray))
var out = {'min' : minDate,
'max': maxDate}
console.log(out)
return out
}
export { appendLegend, formatCalendarContainerSize, formatCalendarSize, addClassToWorkingDays, searchedDateRange }

View File

@ -0,0 +1,179 @@
import { updateCheckedRecords } from './calendar_ajax_hr_module_requests.js'
function detailedRecordsMainBlock(data){
var container = document.createElement('div')
var buttonsContainer = document.createElement('div')
buttonsContainer.id = 'buttons_container'
buttonsContainer.appendChild(addButton('Edit', 'edit', eventListenerEdit))
buttonsContainer.appendChild(addButton('Save', 'save', eventListenerUpdate))
buttonsContainer.appendChild(addButton('Delete', 'delete', eventListenerUpdate))
buttonsContainer.appendChild(addButton('Cancel', 'cancel'))
buttonsContainer.appendChild(addButton('Select all/none', 'checkbox_select', eventListenerSelectAll))
container.appendChild(buttonsContainer)
container.appendChild(detailedCalendarRecordsTable(data))
return container
}
function addButton(innText, name, eventListener=null){
var button = document.createElement('button')
button.innerHTML = innText
button.name = name
button.className = 'change_button'
button.id = name + '_button'
if (eventListener !== null) {
button.addEventListener('click', eventListener)
}
return button
}
function detailedCalendarRecordsTable(data){
var table = createDetailedHeaders()
for (var i = 0; i < data.length; i++){
var index = data[i]['id']
var username = data[i]['username_id']
var row = table.insertRow(-1)
row.id = 'database_id_' + index.toString()
row.className = 'database_row'
row.setAttribute('database_username', username)
appendCell(row, 'div', 'date', data[i]['date'], 0)
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
var cell = row.insertCell(4)
var checkboxContainer = document.createElement('checkbox')
checkboxContainer.className = 'copy_over_checkbox_cell'
checkboxContainer.style.display = 'none'
var checkbox = document.createElement('input')
checkbox.type = 'checkbox'
checkbox.checked = false
checkboxContainer.appendChild(checkbox)
cell.appendChild(checkboxContainer)
}
return table
}
function eventListenerSelectAll(){
var elements = document.getElementsByTagName('input')
for (var i = 0; i < elements.length; i++){
if (elements[i].type == 'checkbox' && elements[i].checked == true){
elements[i].checked = false
} else if (elements[i].type == 'checkbox' && elements[i].checked == false){
elements[i].checked = true
}
}
}
function eventListenerEdit(){
unhideCheckboxes()
unlockRecordsForEditing()
}
function eventListenerUpdate(e){
var action = e.target.name
var data = getCheckedRecords()
updateCheckedRecords(data, action)
}
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
var cell = tableRow.insertCell(cellIndex)
var textInput = document.createElement(tag)
textInput.innerText = tagText
textInput.name = tagName
textInput.className = tagName
cell.appendChild(textInput)
}
function unhideCheckboxes(){
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
for (var i = 0; i < checkboxes.length; i++){
checkboxes[i].style.display = 'initial'
checkboxes[i].firstChild.checked = true
}
var header_copy_over = document.getElementById('header_copy_over')
header_copy_over.style.display = 'table-cell'
}
function unlockRecordsForEditing(){
var rows = document.getElementsByClassName('database_row')
for (var j = 0; j < rows.length; j++) {
var children = rows[j].getElementsByTagName('div')
for (var i = 0; i < children.length; i++) {
if (['begin_time', 'end_time'].includes(children[i].className)) {
var value = children[i].innerText
var name = children[i].className
var input = document.createElement('input')
input.name = name
input.value = value
input.type = 'time'
children[i].innerHTML = ''
children[i].appendChild(input)
}
}
}
}
function getCheckedRecords(){
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
var outputArray = []
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].firstChild.checked == true) {
console.log('checked', i)
var jsonChecked = {}
var row = checkboxes[i].parentNode.parentNode
var id = row.id.split('_')
id = id[id.length-1]
var username = row.getAttribute('database_username')
var beginTime = row.querySelectorAll('input[name="begin_time"]')[0].value
var endTime = row.querySelectorAll('input[name="end_time"]')[0].value
jsonChecked['id'] = parseInt(id)
jsonChecked['username'] = username
jsonChecked['begin_time'] = beginTime
jsonChecked['end_time'] = endTime
outputArray.push(jsonChecked)
}
}
return outputArray
}
function formatTableSize(){
var calendar = document.getElementById('calendar_container')
var tableDiv = document.getElementById('list_container')
var width = calendar.offsetWidth
tableDiv.setAttribute('style', 'width:' + width + 'px')
}
function createDetailedHeaders(){
var table = document.createElement('table')
let headerRow = document.createElement('tr')
let columns = ['Date', 'Start time', 'End time', 'Activity type', 'Copy over']
for (let i = 0; i < columns.length; i++){
var headerCell = document.createElement('th')
var headerText = document.createElement('div')
headerText.innerText = columns[i]
headerCell.appendChild(headerText)
if (i == columns.length -1){
headerCell.style.display = 'none'
headerCell.id = 'header_copy_over'
}
headerRow.appendChild(headerCell)
}
table.appendChild(headerRow)
table.id = 'detailed_plan_records'
return table
}
export { detailedRecordsMainBlock, getCheckedRecords, formatTableSize }

View File

@ -1,17 +0,0 @@
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}

View File

@ -1,4 +1,4 @@
const csrftoken = getCookie('csrftoken');
import {csrftoken} from "../../../static/js/csrf_token.js";
var searchEmployeeButton = document.getElementById('load_employee_data_button')
searchEmployeeButton.addEventListener('click', function(){

View File

@ -1,5 +1,5 @@
const csrftoken = getCookie('csrftoken');
import { csrftoken } from '../../../static/js/csrf_token.js'
window.addEventListener('load', function (){
fetchSearchOptions()
@ -48,10 +48,10 @@ function appendFoundFilterOptions(data){
var caption = data[i]['caption'];
var value = data[i]['column_value'];
innerHTML = '<option value="' + value + '">' + caption + '</option>'
var innerhtml = '<option value="' + value + '">' + caption + '</option>'
var wrapper = document.createElement('div');
wrapper.innerHTML = innerHTML;
wrapper.innerHTML = innerhtml;
var htmlNode = wrapper.firstChild;
parent.appendChild(htmlNode);
@ -204,7 +204,7 @@ function buildPlanJson(){
var upperBoundary = document.getElementById('planning_upper_boundary').value
for (var i = 0; i < employees.length; i++) {
var planJson = {}
row = employees[0]
var row = employees[0]
var username = row.getAttribute('data-username')
var startTime = row.getElementsByClassName('schedule_time_input')[0].value
var activityType = row.getElementsByClassName('activity_type')[0].value
@ -212,7 +212,7 @@ function buildPlanJson(){
var days = row.getElementsByClassName('working_days')
var daysOfWeek = {}
for (var k = 0; k < days.length; k++){
day = days[k]
var day = days[k]
daysOfWeek[day.value] = day.checked
}
planJson['username'] = username
@ -250,14 +250,3 @@ function postPlanToDb(){
}
function showPopup(){
document.getElementById("popup_content").addEventListener("click", function(e) {
e.stopPropagation();
});
let popup = document.getElementById("login_popup");
if (window.getComputedStyle(popup).getPropertyValue('display') === 'none'){
popup.style.display ='flex';
} else {
popup.style.display ='none';
}
}

View File

@ -0,0 +1,59 @@
import { csrftoken } from '../../../static/js/csrf_token.js'
window.addEventListener('load', function (){
fetchSearchOptions()
var filterType = document.getElementById('schedule_filter_category')
filterType.addEventListener('change', fetchSearchOptions)
var fetchEmployeesButton = document.getElementById('load_employees');
fetchEmployeesButton.addEventListener('click', fetchEmployees);
var submitToDb = document.getElementById('run_planning');
submitToDb.addEventListener('click', postPlanToDb);
})
function fetchSearchOptions() {
var host = 'http://' + window.location.host;
var fetch_url = host + '/hr_module/search_api'
var searched_field = document.getElementById('schedule_filter_category').value
var searched_string = document.getElementById('searched_string').value
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"searched_field": searched_field,
"searched_string": searched_string
}),
}).then((response) => {
return response.json();
}).then((data) => {
appendFoundFilterOptions(data);
});
}
function appendFoundFilterOptions(data){
var parent = document.getElementById('schedule_filter_search');
parent.innerHTML = '';
for (var i = 0; i < data.length; i++) {
var caption = data[i]['caption'];
var value = data[i]['column_value'];
var innerhtml = '<option value="' + value + '">' + caption + '</option>'
var wrapper = document.createElement('div');
wrapper.innerHTML = innerhtml;
var htmlNode = wrapper.firstChild;
parent.appendChild(htmlNode);
}
}

View File

@ -1,377 +0,0 @@
const csrftoken = getCookie('csrftoken');
window.addEventListener('load', function(){
var parent = document.getElementById('calendar_box')
parent.appendChild(addCalendar(monthsAhead=3))
appendLegend()
formatCalendarContainerSize(document.getElementById('calendar_container'))
formatCalendarSize()
document.getElementById('load_schedule_button').addEventListener('click', function(){
fetchDays()
})
document.getElementById('calendar_button_back').addEventListener('click', function(){
fetchDays()
})
document.getElementById('calendar_button_forwards').addEventListener('click', function(){
fetchDays()
})
document.getElementById('button_load_selected_months').addEventListener('click', function(){
fetchDays()
})
})
function fetchDays(){
var host = 'http://' + window.location.host;
var fetch_url = host + '/hr_module/show_employee_plan_api'
var range = searchedDateRange()
var startDate = range['min']
var endDate = range['max']
var username = document.getElementById('username_input').value
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"username": username,
"start_date": startDate,
"end_date" : endDate
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
addClassToWorkingDays(data);
var parent = document.getElementById('hr_module_main_container')
var listContainer = document.getElementById('list_container')
if (listContainer == null){
var listContainer = document.createElement('div')
listContainer.id = 'list_container'
} else {
listContainer.innerHTML = ''
}
listContainer.appendChild(createDetailedCalendarRecords(data))
parent.appendChild(listContainer)
formatTableSize()
});
}
function addClassToWorkingDays(data){
for (var i = 0; i < data.length; i++){
var processedDate = data[i]['date']
var processedActivityType = data[i]['activity_type']
var nodeToChange = document.getElementById('date_' + processedDate)
nodeToChange.classList.add('days_of_month_' + processedActivityType)
}
}
function createDetailedCalendarRecords(data){
var table = createDetailedHeaders()
for (var i = 0; i < data.length; i++){
var index = data[i]['id']
var username = data[i]['username_id']
var row = table.insertRow(-1)
row.id = 'database_id_' + index.toString()
row.setAttribute('database_username', username)
appendCell(row, 'div', 'date', data[i]['date'], 0)
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
var cell = row.insertCell(4)
var buttonContainer = document.createElement('div')
buttonContainer.className = 'buttons_cell'
var button = document.createElement('button')
button.innerText = 'Edit'
button.value = index
button.addEventListener('click', unlockRecordsForEditing)
buttonContainer.appendChild(button)
cell.appendChild(buttonContainer)
var cell = row.insertCell(5)
var checkboxContainer = document.createElement('checkbox')
checkboxContainer.className = 'copy_over_checkbox_cell'
checkboxContainer.style.display = 'none'
var checkbox = document.createElement('input')
checkbox.type = 'checkbox'
checkbox.checked = false
checkboxContainer.appendChild(checkbox)
cell.appendChild(checkboxContainer)
}
return table
}
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
var cell = tableRow.insertCell(cellIndex)
var textInput = document.createElement(tag)
textInput.innerText = tagText
textInput.name = tagName
cell.appendChild(textInput)
}
function unlockRecordsForEditing(event){
var databaseId = event.target.value
var parent = event.target.parentElement
var row = document.getElementById('database_id_' + databaseId.toString())
var children = row.getElementsByTagName('div')
for (var i = 0; i < children.length; i++){
console.log(children[i].className )
if (['begin_time', 'end_time'].includes(children[i].className)) {
var value = children[i].innerText
var name = children[i].className
var input = document.createElement('input')
input.name = name
input.value = value
input.type = 'time'
children[i].innerHTML = ''
children[i].appendChild(input)
}
}
removeEditButtons(databaseId)
parent.appendChild(addSaveButton(databaseId))
parent.appendChild(addDeleteButton(databaseId))
parent.appendChild(addCancelButton(databaseId))
unhideCheckboxes(databaseId)
}
function getCheckedRecords(event){
var id = event.target.value
var row = document.getElementById('database_id_' + id)
var username = row.getAttribute('database_username')
var children = row.getElementsByTagName('input')
var copyValues = {'username': username}
for (var i = 0; i < children.length; i++) {
var fieldName = children[i].name
var fieldvalue = children[i].value
if (fieldName != '') {
copyValues[fieldName] = fieldvalue
}
}
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
var outputArray = []
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].firstChild.checked == true) {
console.log('checked', i)
var jsonChecked = {}
var row = checkboxes[i].parentNode.parentNode
var id = row.id.split('_')
id = id[id.length-1]
jsonChecked['id'] = parseInt(id)
var jsonConcat = Object.assign(jsonChecked, copyValues)
outputArray.push(jsonConcat)
}
}
console.log(outputArray)
return outputArray
}
function updateCheckedRecords(recordsArray, action){
var host = 'http://' + window.location.host;
var fetch_url = host + '/hr_module/update_plan_api'
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
'action': action,
'records': recordsArray,
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
parent.innerHTML = ''
parent.appendChild(addCalendar(3))
formatCalendarContainerSize(document.getElementById('calendar_container'))
})
}
function unhideCheckboxes(databaseId){
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
for (var i = 0; i < checkboxes.length; i++){
checkboxes[i].style.display = 'initial'
if (checkboxes[i].parentNode.parentNode.id == 'database_id_' + databaseId.toString()){
checkboxes[i].firstChild.checked = 'true'
}
}
var header_copy_over = document.getElementById('header_copy_over')
header_copy_over.style.display = 'table-cell'
}
function removeEditButtons(id){
var elements = document.getElementsByClassName('buttons_cell')
for (var i = 0; i < elements.length; i++){
elements[i].innerHTML = ''
}
}
function addSaveButton(databaseId){
var button = document.createElement('button')
button.innerHTML = 'Save'
button.name = 'save'
button.value = databaseId
button.addEventListener('click', function(event){
var checkedRecords = getCheckedRecords(event)
updateCheckedRecords(checkedRecords, 'update')
fetchDays()
})
return button
}
function addDeleteButton(databaseId){
var button = document.createElement('button')
button.innerHTML = 'Delete'
button.name = 'delete'
button.value = databaseId
button.addEventListener('click', function(event){
var checkedRecords = getCheckedRecords(event)
updateCheckedRecords(checkedRecords, 'delete')
fetchDays()
})
return button
}
function addCancelButton(databaseId){
var button = document.createElement('button')
button.innerHTML = 'Cancel'
button.name = 'cancel'
button.value = databaseId
button.addEventListener('click', fetchDays)
return button
}
function createDetailedHeaders(){
var table = document.createElement('table')
let headerRow = document.createElement('tr')
let columns = ['Date', 'Start time', 'End time', 'Activity type', 'Action', 'Copy over']
for (let i = 0; i < columns.length; i++){
var headerCell = document.createElement('th')
var headerText = document.createElement('div')
headerText.innerText = columns[i]
headerCell.appendChild(headerText)
if (i == columns.length -1){
headerCell.style.display = 'none'
headerCell.id = 'header_copy_over'
}
headerRow.appendChild(headerCell)
}
table.appendChild(headerRow)
table.id = 'detailed_plan_records'
return table
}
function formatCalendarContainerSize(calendarContainer){
var monthsBlock = calendarContainer.querySelector('#months_block')
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
var dateSelector = calendarContainer.querySelector('#date_selector')
var legendSelector = calendarContainer.querySelector('#legend_container')
var widthMonths = monthsBlock.offsetWidth
var heightMonths = monthsBlock.offsetHeight
var heightDateSelector = dateSelector.offsetHeight
var heightLegend = legendSelector.offsetHeight
var widthCalendarButton = calendarButton.offsetWidth * 2
var widthTotal = widthMonths + widthCalendarButton
var heightTotal = heightMonths + heightDateSelector + heightLegend
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
}
function formatTableSize(){
var calendar = document.getElementById('calendar_container')
var tableDiv = document.getElementById('list_container')
var width = calendar.offsetWidth
tableDiv.setAttribute('style', 'width:' + width + 'px')
}
function formatCalendarSize(){
var calendarBox = document.getElementById('calendar_box')
var calendar = document.getElementById('calendar_container')
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
}
function searchedDateRange(){
var dates = document.getElementsByClassName('days_of_month_current')
var datesArray = []
for (var i = 0; i < dates.length; i++){
var dateAttr = new Date(dates[i].getAttribute('date'))
datesArray.push(dateAttr)
}
var minDate = new Date(Math.min.apply(null, datesArray))
var maxDate = new Date(Math.max.apply(null, datesArray))
var out = {'min' : minDate,
'max': maxDate}
console.log(out)
return out
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function appendLegend(){
var calendar = document.getElementById('calendar_container')
var container = document.createElement('div')
container.id = 'legend_container'
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
for(var i = 0; i < activityTypes.length; i++){
var legendElementContainer = document.createElement('div')
legendElementContainer.className = 'legend_element_container'
var legendDivText = document.createElement('div')
legendDivText.innerText = activityTypes[i]
legendDivText.className = 'legend_label'
var legendDivBox = document.createElement('div')
legendDivBox.classList.add('legend_cube')
legendDivBox.classList.add('days_of_month_' + activityTypes[i])
legendElementContainer.appendChild(legendDivText)
legendElementContainer.appendChild(legendDivBox)
container.appendChild(legendElementContainer)
}
calendar.appendChild(container)
}

View File

@ -1,378 +0,0 @@
const csrftoken = getCookie('csrftoken');
window.addEventListener('load', function(){
var parent = document.getElementById('calendar_box')
parent.appendChild(addCalendar(monthsAhead=3))
appendLegend()
formatCalendarContainerSize(document.getElementById('calendar_container'))
formatCalendarSize()
document.getElementById('load_schedule_button').addEventListener('click', function(){
fetchDays()
})
document.getElementById('calendar_button_back').addEventListener('click', function(){
fetchDays()
})
document.getElementById('calendar_button_forwards').addEventListener('click', function(){
fetchDays()
})
document.getElementById('button_load_selected_months').addEventListener('click', function(){
fetchDays()
})
})
function fetchDays(){
var host = 'http://' + window.location.host;
var fetch_url = host + '/hr_module/show_employee_timelog_api'
var range = searchedDateRange()
var startDate = range['min']
var endDate = range['max']
var username = document.getElementById('username_input').value
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
"username": username,
"start_date": startDate,
"end_date" : endDate
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
addClassToWorkingDays(data);
var parent = document.getElementById('hr_module_main_container')
var listContainer = document.getElementById('list_container')
if (listContainer == null){
var listContainer = document.createElement('div')
listContainer.id = 'list_container'
} else {
listContainer.innerHTML = ''
}
listContainer.appendChild(createDetailedCalendarRecords(data))
parent.appendChild(listContainer)
formatTableSize()
});
}
function addClassToWorkingDays(data){
for (var i = 0; i < data.length; i++){
var processedDate = data[i]['date']
var processedActivityType = data[i]['activity_type']
var nodeToChange = document.getElementById('date_' + processedDate)
nodeToChange.classList.add('days_of_month_' + processedActivityType)
}
}
function createDetailedCalendarRecords(data){
var table = createDetailedHeaders()
for (var i = 0; i < data.length; i++){
var index = data[i]['id']
var username = data[i]['username_id']
var row = table.insertRow(-1)
row.id = 'database_id_' + index.toString()
row.setAttribute('database_username', username)
appendCell(row, 'div', 'date', data[i]['date'], 0)
appendCell(row, 'div', 'begin_time', data[i]['begin_time'], 1)
appendCell(row, 'div', 'end_time', data[i]['end_time'], 2)
appendCell(row, 'div', 'activity_type', data[i]['activity_type'], 3)
var cell = row.insertCell(4)
var buttonContainer = document.createElement('div')
buttonContainer.className = 'buttons_cell'
var button = document.createElement('button')
button.innerText = 'Edit'
button.value = index
button.addEventListener('click', unlockRecordsForEditing)
buttonContainer.appendChild(button)
cell.appendChild(buttonContainer)
var cell = row.insertCell(5)
var checkboxContainer = document.createElement('checkbox')
checkboxContainer.className = 'copy_over_checkbox_cell'
checkboxContainer.style.display = 'none'
var checkbox = document.createElement('input')
checkbox.type = 'checkbox'
checkbox.checked = false
checkboxContainer.appendChild(checkbox)
cell.appendChild(checkboxContainer)
}
return table
}
function appendCell(tableRow, tag, tagName, tagText, cellIndex){
var cell = tableRow.insertCell(cellIndex)
var textInput = document.createElement(tag)
textInput.innerText = tagText
textInput.name = tagName
cell.appendChild(textInput)
}
function unlockRecordsForEditing(event){
var databaseId = event.target.value
var parent = event.target.parentElement
var row = document.getElementById('database_id_' + databaseId.toString())
var children = row.getElementsByTagName('div')
for (var i = 0; i < children.length; i++){
console.log(children[i].className )
if (['begin_time', 'end_time'].includes(children[i].className)) {
var value = children[i].innerText
var name = children[i].className
var input = document.createElement('input')
input.name = name
input.value = value
input.type = 'time'
children[i].innerHTML = ''
children[i].appendChild(input)
}
}
removeEditButtons(databaseId)
parent.appendChild(addSaveButton(databaseId))
parent.appendChild(addDeleteButton(databaseId))
parent.appendChild(addCancelButton(databaseId))
unhideCheckboxes(databaseId)
}
function getCheckedRecords(event){
var id = event.target.value
var row = document.getElementById('database_id_' + id)
var username = row.getAttribute('database_username')
var children = row.getElementsByTagName('input')
var copyValues = {'username': username}
for (var i = 0; i < children.length; i++) {
var fieldName = children[i].name
var fieldvalue = children[i].value
if (fieldName != '') {
copyValues[fieldName] = fieldvalue
}
}
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
var outputArray = []
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].firstChild.checked == true) {
console.log('checked', i)
var jsonChecked = {}
var row = checkboxes[i].parentNode.parentNode
var id = row.id.split('_')
id = id[id.length-1]
jsonChecked['id'] = parseInt(id)
var jsonConcat = Object.assign(jsonChecked, copyValues)
outputArray.push(jsonConcat)
}
}
console.log(outputArray)
return outputArray
}
function updateCheckedRecords(recordsArray, action){
var host = 'http://' + window.location.host;
var fetch_url = host + '/hr_module/update_timelog_api'
fetch(fetch_url,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRFToken': csrftoken
},
body: JSON.stringify({
'action': action,
'records': recordsArray,
}),
}).then((response) => {
return response.json();
}).then((data) => {
console.log(data);
parent.innerHTML = ''
parent.appendChild(addCalendar(3))
formatCalendarContainerSize(document.getElementById('calendar_container'))
})
}
function unhideCheckboxes(databaseId){
var checkboxes = document.getElementsByClassName('copy_over_checkbox_cell')
for (var i = 0; i < checkboxes.length; i++){
checkboxes[i].style.display = 'initial'
if (checkboxes[i].parentNode.parentNode.id == 'database_id_' + databaseId.toString()){
checkboxes[i].firstChild.checked = 'true'
}
}
var header_copy_over = document.getElementById('header_copy_over')
header_copy_over.style.display = 'table-cell'
}
function removeEditButtons(id){
var elements = document.getElementsByClassName('buttons_cell')
for (var i = 0; i < elements.length; i++){
elements[i].innerHTML = ''
}
}
function addSaveButton(databaseId){
var button = document.createElement('button')
button.innerHTML = 'Save'
button.name = 'save'
button.value = databaseId
button.addEventListener('click', function(event){
var checkedRecords = getCheckedRecords(event)
updateCheckedRecords(checkedRecords, 'update')
fetchDays()
})
return button
}
function addDeleteButton(databaseId){
var button = document.createElement('button')
button.innerHTML = 'Delete'
button.name = 'delete'
button.value = databaseId
button.addEventListener('click', function(event){
var checkedRecords = getCheckedRecords(event)
updateCheckedRecords(checkedRecords, 'delete')
fetchDays()
})
return button
}
function addCancelButton(databaseId){
var button = document.createElement('button')
button.innerHTML = 'Cancel'
button.name = 'cancel'
button.value = databaseId
button.addEventListener('click', fetchDays)
return button
}
function createDetailedHeaders(){
var table = document.createElement('table')
let headerRow = document.createElement('tr')
let columns = ['Date', 'Start time', 'End time', 'Activity type', 'Action', 'Copy over']
for (let i = 0; i < columns.length; i++){
var headerCell = document.createElement('th')
var headerText = document.createElement('div')
headerText.innerText = columns[i]
headerCell.appendChild(headerText)
if (i == columns.length -1){
headerCell.style.display = 'none'
headerCell.id = 'header_copy_over'
}
headerRow.appendChild(headerCell)
}
table.appendChild(headerRow)
table.id = 'detailed_plan_records'
return table
}
function formatCalendarContainerSize(calendarContainer){
var monthsBlock = calendarContainer.querySelector('#months_block')
var calendarButton = calendarContainer.querySelector('#calendar_button_back')
var dateSelector = calendarContainer.querySelector('#date_selector')
var legendSelector = calendarContainer.querySelector('#legend_container')
var widthMonths = monthsBlock.offsetWidth
var heightMonths = monthsBlock.offsetHeight
var heightDateSelector = dateSelector.offsetHeight
var heightLegend = legendSelector.offsetHeight
var widthCalendarButton = calendarButton.offsetWidth * 2
var widthTotal = widthMonths + widthCalendarButton
var heightTotal = heightMonths + heightDateSelector + heightLegend
calendarContainer.setAttribute('style','height:' + heightTotal +'px; width:' + widthTotal + 'px');
}
function formatTableSize(){
var calendar = document.getElementById('calendar_container')
var tableDiv = document.getElementById('list_container')
var width = calendar.offsetWidth
tableDiv.setAttribute('style', 'width:' + width + 'px')
}
function formatCalendarSize(){
var calendarBox = document.getElementById('calendar_box')
var calendar = document.getElementById('calendar_container')
calendarBox.setAttribute('style', 'width:' + calendar.offsetWidth + 'px')
}
function searchedDateRange(){
var dates = document.getElementsByClassName('days_of_month_current')
var datesArray = []
for (var i = 0; i < dates.length; i++){
var dateAttr = new Date(dates[i].getAttribute('date'))
datesArray.push(dateAttr)
}
var minDate = new Date(Math.min.apply(null, datesArray))
var maxDate = new Date(Math.max.apply(null, datesArray))
var out = {'min' : minDate,
'max': maxDate}
console.log(out)
return out
}
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
let cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function appendLegend(){
var calendar = document.getElementById('calendar_container')
var container = document.createElement('div')
container.id = 'legend_container'
var activityTypes = ['work', 'vacation', 'sickness', 'parental_leave']
for(var i = 0; i < activityTypes.length; i++){
var legendElementContainer = document.createElement('div')
legendElementContainer.className = 'legend_element_container'
var legendDivText = document.createElement('div')
legendDivText.innerText = activityTypes[i]
legendDivText.className = 'legend_label'
var legendDivBox = document.createElement('div')
legendDivBox.classList.add('legend_cube')
legendDivBox.classList.add('days_of_month_' + activityTypes[i])
legendElementContainer.appendChild(legendDivText)
legendElementContainer.appendChild(legendDivBox)
container.appendChild(legendElementContainer)
}
calendar.appendChild(container)
}

View File

@ -8,7 +8,6 @@
{% block core_content %}
<script src="{% static '/js/csrf_token.js' %}"></script>
<div id="sidebar">
@ -51,7 +50,7 @@
</a>
<a href="{% url 'hr_module:create_schedule' %}">
<a href="{% url 'hr_module:export' %}">
<div class="sidebar_item" >Export data
</div>
</a>

View File

@ -15,6 +15,6 @@
</div>
<script src="{% static '/js/hr_module_change_employee_data.js' %}"></script>
<script type="module" src="{% static '/js/hr_module_change_employee_data.js' %}"></script>
{% endblock %}

View File

@ -56,6 +56,6 @@
</div>
<script src="{% static '/js/hr_module_create_schedule.js' %}"></script>
<script type="module" src="{% static '/js/hr_module_create_schedule.js' %}"></script>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends 'hr_module_base.html' %}
{% load static %}
{% block action_panel %}
<link rel="stylesheet" href="{% static '/css/hr_module_create_schedule.css' %}">
<form method="POST">
{% csrf_token %}
<div class="search_row">
<div class="search_element">Select filter type:
<select name="category" id="schedule_filter_category">
<option value="username">Person</option>
<option value="manager">Manager</option>
<option value="department">Department</option>
</select>
</div>
<div class="search_element">
<input name="searched_string" list="schedule_filter_search" id="searched_string" autocomplete="off" >
<datalist id="schedule_filter_search">
</datalist>
</div>
</div>
<div class="search_row">
<div class="search_element">
<input name="date_start" type="date" id="date_start" autocomplete="off" >
</div>
<div class="search_element">
<input name="date_end" type="date" id="date_end" autocomplete="off" >
</div>
</div>
<div class="search_row">
<div class="search_element">
<button type="submit" id="download_report">Download report</button>
</div>
</div>
</form>
<script type="module" src="{% static '/js/hr_module_export.js' %}"></script>
{% endblock %}

View File

@ -1,16 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block core_content %}
<h4>Please login</h4>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}

View File

@ -1,16 +0,0 @@
{% extends 'base.html' %}
{% load static %}
{% block core_content %}
<h4>Please change your password</h4>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
{% endblock %}

View File

@ -14,8 +14,7 @@
</div>
<div id="calendar_box"></div>
<script src="{% static '/js/calendar.js' %}"></script>
<script src="{% static '/js/hr_module_show_schedule.js' %}"></script>
<script type="module" src="{% static '/js/../../static/js/calendar_ajax_hr_module_main.js' %}"></script>
{% endblock %}

View File

@ -14,8 +14,6 @@
</div>
<div id="calendar_box"></div>
<script src="{% static '/js/calendar.js' %}"></script>
<script src="{% static '/js/hr_module_show_timelog.js' %}"></script>
<script type="module" src="{% static '/js/../../static/js/calendar_ajax_hr_module_main.js' %}"></script>
{% endblock %}

View File

@ -6,22 +6,21 @@ from django.contrib.auth import views as auth_views
app_name = 'hr_module'
urlpatterns = [
path('login', auth_views.LoginView.as_view(template_name='hr_module_login.html'), name='login'),
path('logout', auth_views.LogoutView.as_view(), name='logout'),
path('change_password', auth_views.PasswordChangeView.as_view(template_name='hr_module_password_change.html'), name='change_password'),
path('home', views.homepage, name='homepage'),
path('create_schedule', views.create_schedule, name='create_schedule'),
path('create_employees', views.create_employees, name='create_employees'),
path('search_api', views.search_users_api, name='search_users_api'),
path('loademployees', views.load_employees_api, name='load_employees'),
path('new_plan_api', views.new_plan_api, name='new_plan_api'),
path('manage_schedule', views.manage_schedule, name='manage_schedule'),
path('show_schedule', views.manage_schedule, name='manage_schedule'),
path('show_employee_plan_api', views.show_employee_plan_api, name='show_employee_plan_api'),
path('update_plan_api', views.update_plan_api, name='update_plan_api'),
path('manage_timelog', views.manage_timelog, name='manage_timelog'),
path('show_timelog', views.manage_timelog, name='manage_timelog'),
path('show_employee_timelog_api', views.show_employee_timelog_api, name='show_employee_timelog_api'),
path('update_timelog_api', views.update_timelog_api, name='update_timelog_api'),
path('change_employee_data', views.change_employee_data, name='change_employee_data'),
path('change_employee_data_api', views.change_employee_data_api, name='change_employee_data_api'),
path('plan_creation_log', views.plan_creation_log, name='plan_creation_log'),
path('export', views.export, name='export'),
]

View File

@ -5,18 +5,20 @@ from hr_module.handling_functions.data_import_functions import read_and_parse_ex
from hr_module.handling_functions.misc import dictfetchall
from hr_module.handling_functions.insert_to_plan import UpdatePlan
from hr_module.handling_functions.monthly_planning_functions import create_planning_operation_report
from hr_module.sql_queries import export_queries
import pandas as pd
import json
from .models import Employee, PlanCreationLog, Plan, TimeLog
from django.contrib.auth.models import User
from django.http import HttpResponse, JsonResponse, Http404, HttpResponseRedirect
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
from django.db import connection
import datetime
from django.urls import reverse
from django.urls import reverse, reverse_lazy
from django.conf import settings
import csv
login_url = '/hr_module/login'
login_url = reverse_lazy('login')
# Create your views here.
@login_required(login_url=login_url)
def create_schedule(request):
@ -84,7 +86,6 @@ def change_employee_data_api(request):
response_dict = dict(record_user, **record_employee)
for i in ['_state', 'password']:
response_dict.pop(i)
print(response_dict)
return JsonResponse(response_dict, safe=False)
else:
return JsonResponse({'error': 'not_authenticated'})
@ -98,7 +99,6 @@ def create_employees(request):
if request.method == 'POST':
if 'import_preview' in request.POST:
fileform = UploadFileForm(request.POST, request.FILES)
print(fileform.is_valid())
if fileform.is_valid():
uploaded_file = request.FILES['file']
df_dict = read_and_parse_excel(uploaded_file)
@ -123,7 +123,6 @@ def create_employees(request):
df_dict.pop(i, None)
df = pd.DataFrame(df_dict, index=[0])
insert_excel(df)
print('done')
template = 'hr_module_import_success.html'
return render(request, template)
@ -156,7 +155,6 @@ def search_users_api(request):
body = json.loads(request.body)
searched_field = body['searched_field']
searched_string = body['searched_string']
print(searched_field, searched_string)
cursor = connection.cursor()
@ -175,7 +173,6 @@ def search_users_api(request):
)
response = dictfetchall(cursor)
print(response)
return JsonResponse(response, safe=False)
@ -184,12 +181,10 @@ def load_employees_api(request):
body = json.loads(request.body)
searched_field = body['searched_field']
searched_string = body['searched_string']
print(searched_field, searched_string)
cursor = connection.cursor()
if searched_field == 'department':
print('Deparment executed')
cursor.execute('select auth.first_name || %s || auth.last_name as name, auth.username as username, '
'empl.manager_username as manager_name, tm.daily_hours, '
'tm.mon, tm.tue, tm.wed, tm.thu, tm.fri, tm.sat, tm.fri '
@ -198,7 +193,6 @@ def load_employees_api(request):
'where department = %s', [' ', searched_string])
elif searched_field == 'manager':
print('Manager executed')
cursor.execute('select auth.first_name || %s || auth.last_name as name, auth.username as username, '
'empl.manager_username as manager_name, tm.daily_hours, '
'tm.mon, tm.tue, tm.wed, tm.thu, tm.fri, tm.sat, tm.fri '
@ -207,7 +201,6 @@ def load_employees_api(request):
'where manager_username = %s', [' ', searched_string])
elif searched_field == 'username':
print('Username executed')
cursor.execute('select auth.first_name || %s || auth.last_name as name, auth.username as username, '
'empl.manager_username as manager_name, tm.daily_hours, '
'tm.mon, tm.tue, tm.wed, tm.thu, tm.fri, tm.sat, tm.sun '
@ -217,7 +210,6 @@ def load_employees_api(request):
'where empl.username = %s ', [' ', searched_string])
response = dictfetchall(cursor)
print(response)
return JsonResponse(response, safe=False)
@ -266,7 +258,6 @@ def show_employee_plan_api(request):
def update_plan_api(request):
if request.method == 'POST':
body = json.loads(request.body)
print(body)
if body['action'] == 'delete':
for i in body['records']:
record_id = i['id']
@ -315,7 +306,6 @@ def show_employee_timelog_api(request):
def update_timelog_api(request):
if request.method == 'POST':
body = json.loads(request.body)
print(body)
if body['action'] == 'delete':
for i in body['records']:
record_id = i['id']
@ -339,6 +329,9 @@ def update_timelog_api(request):
def plan_creation_log(request):
session_user = User.objects.select_related('employee').get(username=request.user.username)
session_user_manager_flag = session_user.employee.manager_flag
if not session_user_manager_flag and not request.user.is_superuser:
return HttpResponseRedirect(reverse('employee_module:homepage'))
if request.user.is_superuser:
creation_log = PlanCreationLog.objects.all().order_by('-creation_date')
elif session_user_manager_flag:
@ -348,4 +341,50 @@ def plan_creation_log(request):
'path': settings.IMPORT_REPORT_STORAGE}
template_name = 'hr_module_creation_log.html'
return render(request, context=context, template_name=template_name)
return render(request, context=context, template_name=template_name)
@login_required(login_url=login_url)
def export(request):
session_user = User.objects.select_related('employee').get(username=request.user.username)
if not session_user.employee.manager_flag and not request.user.is_superuser:
return HttpResponseRedirect(reverse('employee_module:homepage'))
if request.method == 'POST':
category = request.POST.get('category')
searched_string = request.POST.get('searched_string')
date_start = request.POST.get('date_start')
date_end = request.POST.get('date_end')
months = months_list(date_start, date_end)
query = export_queries[category]
cursor = connection.cursor()
cursor.execute(query.format(months, searched_string))
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="time_report.csv"'
resp = dictfetchall(cursor)
writer = csv.writer(response)
writer.writerow([k for k in resp[0].keys()])
for row in resp:
writer.writerow([v for v in row.values()])
return response
template = 'hr_module_export.html'
return render(request, template)
def months_list(start_date, end_date):
start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
tmp = end_date
list_ = []
while tmp >= start_date:
list_.append(tmp.strftime('%Y-%m'))
tmp = tmp.replace(day=1) - datetime.timedelta(days=1)
start_date_str = start_date.strftime('%Y-%m')
if not start_date_str in list_:
list_.append(start_date_str)
return tuple(list_)

View File

@ -6,8 +6,11 @@ html, body {
}
.navbar {
height: 50px;
background-color: #D3D3D3;
background-color: #202831;
width: 100%;
border-bottom: #7F8B94 thin solid;
color: #7F8B94;
}
.main_container {
background-color: whitesmoke;
@ -25,6 +28,7 @@ html, body {
text-align:center;
margin-top: 15px;
margin-right: 15px;
text-decoration: none;
}
#calendar_box, #list_container {

View File

@ -14,4 +14,8 @@ function getCookie(name) {
}
}
return cookieValue;
}
}
const csrftoken = getCookie('csrftoken');
export { csrftoken }

View File

@ -15,7 +15,7 @@
{% if user.is_authenticated %}
<div class="navbar_item">
<a href="{% url 'hr_module:logout' %}">Log out</a>
<a href="{% url 'logout' %}">Log out</a>
</div>
<div class="navbar_item">You are logged in as: {{ user }} </div>

View File

@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/
from pathlib import Path
import os
from django.urls import reverse_lazy
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@ -66,7 +67,7 @@ TEMPLATES = [
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'hr_module.context_processors.report_download_path',
'hr_module.context_processors.manager_flag',
'django.template.context_processors.media',
'django.template.context_processors.debug',
'django.template.context_processors.request',
@ -138,11 +139,11 @@ STATICFILES_DIRS = [
LOGOUT_REDIRECT_URL = '/hr_module/login'
LOGIN_REDIRECT_URL = '/hr_module/home'
LOGOUT_REDIRECT_URL = reverse_lazy('login')
LOGIN_REDIRECT_URL = reverse_lazy('hr_module:homepage')
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
TMP_FILE_STORAGE = os.path.join(MEDIA_URL, 'temp/')
IMPORT_REPORT_STORAGE = os.path.join(BASE_DIR, 'import_reports')
TMP_FILE_STORAGE = os.path.join(MEDIA_ROOT, 'temp/')
IMPORT_REPORT_STORAGE = os.path.join(MEDIA_ROOT, 'import_reports/')

Some files were not shown because too many files have changed in this diff Show More