From 5dc61e9d6a760e3a86b0bb459c0a628941069d95 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 7 Jul 2019 23:40:09 +0400 Subject: =?UTF-8?q?WIP:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- day9/task5/static/css/ContentBoxStyle.css | 26 +++ day9/task5/static/css/FormStyle.css | 60 ++++++ day9/task5/static/css/NewEntryStyle.css | 32 +++ day9/task5/static/css/TableStyle.css | 23 +++ day9/task5/static/images/upload_icon.png | Bin 0 -> 57084 bytes day9/task5/static/js/config.js | 1 + day9/task5/static/js/main.js | 317 ++++++++++++++++++++++++++++++ 7 files changed, 459 insertions(+) create mode 100644 day9/task5/static/css/ContentBoxStyle.css create mode 100644 day9/task5/static/css/FormStyle.css create mode 100644 day9/task5/static/css/NewEntryStyle.css create mode 100644 day9/task5/static/css/TableStyle.css create mode 100644 day9/task5/static/images/upload_icon.png create mode 100644 day9/task5/static/js/config.js create mode 100644 day9/task5/static/js/main.js (limited to 'day9/task5/static') diff --git a/day9/task5/static/css/ContentBoxStyle.css b/day9/task5/static/css/ContentBoxStyle.css new file mode 100644 index 0000000..78c37d6 --- /dev/null +++ b/day9/task5/static/css/ContentBoxStyle.css @@ -0,0 +1,26 @@ +.contentBox { + padding: 20px; + width: 500px; + height: 520px; + background-color: #f0f0f0; + border-radius: 10px; + box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.3); +} + +.backgroundTint { + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.6); +} + +.shown { + display: inline; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +} + +.hidden { + display: none; +} \ No newline at end of file diff --git a/day9/task5/static/css/FormStyle.css b/day9/task5/static/css/FormStyle.css new file mode 100644 index 0000000..2659a68 --- /dev/null +++ b/day9/task5/static/css/FormStyle.css @@ -0,0 +1,60 @@ +.formRow { + width: 100%; + display: flex; + flex-direction: column; +} + +.formRow-label { + font-size: 13px; + color: #404040; +} + +.formRow-input > input, .formRow-input > select { + margin: 3px; + width: 100%; + border-radius: 5px; + border: none; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2); + padding: 5px; + + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.formRow-input > input:disabled { + background-color: #bebebe; + color: #4b4b4b; +} + +.formInput[type="date"], .formInput[type="time"] { + padding: 5px; + font-size: 1.1em; +} + +.formRow-input > select:hover, .formRow-input > input:not([disabled]):hover { + background-color: #fbfbfb; +} + +.formButtons { + display: flex; + flex-direction: row; + margin-top: 5px; +} + +.formButtons > button { + margin: 5px; + width: 50%; + padding: 5px; + border: none; + border-radius: 7px; + box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.4); +} + +.formButtons > button:hover { + background-color: #dadada; +} + +.formButtons > button:focus { + background-color: #d5d5d5; +} \ No newline at end of file diff --git a/day9/task5/static/css/NewEntryStyle.css b/day9/task5/static/css/NewEntryStyle.css new file mode 100644 index 0000000..e1141b2 --- /dev/null +++ b/day9/task5/static/css/NewEntryStyle.css @@ -0,0 +1,32 @@ +.newEntryBtn { + overflow: hidden; + white-space: nowrap; + + position: fixed; + bottom: 50px; + left: 50px; + + padding: 5px; + border-radius: 20px; + width: 40px; + height: 40px; + border: none; + background-color: #2871e2; + color: white; + font-size: 20px; + + transition-property: width, font-size; + transition-duration: 0.6s; +} + +.newEntryBtn:hover { + width: 150px; + font-size: 15px; + background-color: #286bd6; +} + +.newEntryBtn:focus { + width: 200px; + font-size: 15px; + background-color: #2861c3; +} diff --git a/day9/task5/static/css/TableStyle.css b/day9/task5/static/css/TableStyle.css new file mode 100644 index 0000000..61f2f28 --- /dev/null +++ b/day9/task5/static/css/TableStyle.css @@ -0,0 +1,23 @@ +table { + border-spacing: 0; + padding: 0; + border: 1px solid black; +} + +thead > tr > th { + padding: 6px; + font-size: 16px; + background-color: #6f6f6f; +} + +td { + padding: 3px; + font-size: 13px; +} + +.odd { background-color: #dedede; } +.even { background-color: #c5c5c5; } + +.editableField:hover { + background-color: rgba(0, 0, 0, 0.3); +} diff --git a/day9/task5/static/images/upload_icon.png b/day9/task5/static/images/upload_icon.png new file mode 100644 index 0000000..1e552a3 Binary files /dev/null and b/day9/task5/static/images/upload_icon.png differ diff --git a/day9/task5/static/js/config.js b/day9/task5/static/js/config.js new file mode 100644 index 0000000..815f363 --- /dev/null +++ b/day9/task5/static/js/config.js @@ -0,0 +1 @@ +HOST = 'http://localhost:8000'; diff --git a/day9/task5/static/js/main.js b/day9/task5/static/js/main.js new file mode 100644 index 0000000..63a025e --- /dev/null +++ b/day9/task5/static/js/main.js @@ -0,0 +1,317 @@ +const request = { + get: function (url, callback) { + let xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if (xmlHttp.readyState === 4 && xmlHttp.status === 200) + callback(xmlHttp.responseText); + }; + xmlHttp.open("GET", url, true); + xmlHttp.send(); + }, + + post: function (url, callback, data) { + let xmlHttp = new XMLHttpRequest(); + xmlHttp.onreadystatechange = function() { + if (xmlHttp.readyState === 4 && xmlHttp.status === 200) + callback(xmlHttp.responseText); + }; + xmlHttp.open("POST", url, true); + xmlHttp.send(this.formatParams(data)); + }, + + formatParams: function (params) { + return Object.keys(params).map((key) => { + return key+"="+encodeURIComponent(params[key]) + }).join("&") + } + }; + + const defaultColumnInputs = { + 'service_id': ``, + 'servtype': ``, + 'subtype': ``, + 'user_id': ``, + 'referrer_user_id': ``, + 'state': ``, + + 'creation_date': ``, + 'creation_time': ``, + 'creation_request_sent_date': ``, + 'notified_about_expiration': `` + }; + + const baseFormFields = `
+
+
service_id
+
+
+
servtype
+
+ +
+
+ +
+
subtype
+
+ +
+
+ +
+
user_id
+
+ +
+
+ +
+
referrer_user_id
+
+ +
+
+ +
+
state
+
+ +
+
+ +
+
creation_date
+
+ +
+
+
+
creation_time
+
+ +
+
+ +
+
creation_request_sent_date
+
+ + +
+
+ +
+
notified_about_expiration
+
+ +
+
+
`; + + const formCreateButtons = `
+ + +
`; + + const formEditButtons = `
+ + +
`; + + function elementFromHTML(html) { + let elem = document.createElement('div'); + elem.innerHTML = html; + return elem.firstChild; + } + + function onPageLoad() { + request.post(`${HOST}/get`, renderTable, {'type': 'full'}); + } + + function onFieldClick(fieldId) { + let fieldElement = document.getElementById(fieldId); + + if (fieldElement.firstChild.nodeName !== 'INPUT' && fieldElement.firstChild.nodeName !== 'SELECT') { + let [columnName, serviceId] = fieldId.split('-'); + fieldElement.innerHTML = defaultColumnInputs[columnName]; + if (columnName === 'creation_request_sent_date') { + let dateElement = fieldElement.firstChild; + let timeElement = fieldElement.childNodes[1]; + + dateElement.onkeyup = timeElement.onkeyup = (event) => { + if (event.code === 'Enter') { + if (dateElement.value !== '' && timeElement.value !== '') + fieldEditSubmit(fieldId, `${dateElement.value} ${timeElement.value}`); + } + }; + } + else { + let inputElement = fieldElement.firstChild; + inputElement.onkeyup = (event) => { + if (event.code === 'Enter') + fieldEditSubmit(fieldId, inputElement.value); + }; + } + } + } + + function fieldEditSubmit(fieldId, value) { + let [columnName, serviceId] = fieldId.split('-'); + request.post(`${HOST}/api/update`, () => {}, { + 'service_id': serviceId, [columnName]: value + }); + document.getElementById(fieldId).innerHTML = value; + } + + function renderTable(text) { + let data = JSON.parse(text); + + let table = document.getElementById('table'); + + while (table.firstChild) table.removeChild(table.firstChild); + + let tableHeaders = document.createElement('thead'); + let headerRow = document.createElement('tr'); + tableHeaders.appendChild(headerRow); + data['headers'].forEach((field) => { + let header = document.createElement('th'); + header.innerText = field; + headerRow.appendChild(header); + }); + headerRow.appendChild(document.createElement('th')); + headerRow.appendChild(document.createElement('th')); + + let tableContent = document.createElement('tbody'); + data['content'].forEach((row, rowIndex) => { + row.push(``); + row.push(``); + + let contentRow = document.createElement('tr'); + contentRow.setAttribute('id', `row_${row[0]}`); + + row.forEach((column, colIndex) => { + let color = (colIndex % 2 + rowIndex % 2) % 2 === 0 ? 'odd' : 'even'; + let columnNode = document.createElement('td'); + + if (colIndex !== 0 && colIndex < data['headers'].length) { + let fieldId = `${data['headers'][colIndex]}-${row[0]}`; + columnNode.classList.add('editableField'); + columnNode.onclick = () => { onFieldClick(fieldId) }; + columnNode.setAttribute('id', fieldId); + } + + columnNode.classList.add(color); + columnNode.innerHTML = column; + contentRow.appendChild(columnNode); + }); + + tableContent.appendChild(contentRow); + }); + + table.appendChild(tableHeaders); + table.appendChild(tableContent); + } + + function setupEditFields(service_id) { + showEditForm(); + request.post(`${HOST}/get`, (text) => { + let row = JSON.parse(text); + + Object.keys(row).forEach((element) => { + document.getElementsByName(element)[0].value = row[element]; + }); + + let [sent_date, sent_time] = row['creation_request_sent_date'].split(' '); + document.getElementsByName('creation_request_sent_date')[0].value = sent_date; + document.getElementsByName('creation_request_sent_time')[0].value = sent_time; + }, { + 'type': 'single_id', 'service_id': service_id + }); + } + + function removeField(service_id) { + request.post(`${HOST}/api/delete`, () => {}, {'service_id': service_id}); + let tableBody = document.getElementById('table').childNodes[1]; + for (let node of tableBody.childNodes) { + if (node.getAttribute('id') === `row_${service_id}`) { + tableBody.removeChild(node); + break + } + } + } + + function showContentBox() { + let elem = document.getElementById('backgroundTint'); + elem.classList.remove('hidden'); + elem.classList.add('shown'); + + elem = document.getElementById('contentBox'); + elem.classList.remove('hidden'); + elem.classList.add('shown'); + } + + function hideContentBox() { + let elem = document.getElementById('backgroundTint'); + elem.classList.remove('shown'); + elem.classList.add('hidden'); + + elem = document.getElementById('contentBox'); + elem.classList.remove('shown'); + elem.classList.add('hidden'); + } + + function showForm() { + let newEntryBtn = document.getElementById('newEntryBtn'); + newEntryBtn.style.display = 'none'; + + showContentBox(); + let contentBox = document.getElementById('contentBox'); + while (contentBox.firstChild) + contentBox.removeChild(contentBox.firstChild); + + contentBox.appendChild(elementFromHTML(baseFormFields)); + return contentBox; + } + + showEditForm = () => { + let contentBox = showForm(); + contentBox.appendChild(elementFromHTML(formEditButtons)); + }; + + showCreateForm = () => { + let contentBox = showForm(); + contentBox.appendChild(elementFromHTML(formCreateButtons)); + }; + + function hideForm() { + let newEntryBtn = document.getElementById('newEntryBtn'); + newEntryBtn.style.display = 'inline'; + + let contentBox = document.getElementById('contentBox'); + while (contentBox.firstChild) + contentBox.removeChild(contentBox.firstChild); + + hideContentBox(); + } + + function addNewRowOnHover() { + let btn = document.getElementById('newEntryBtn'); + btn.innerText = 'Add new row'; + } + + function addNewRowOnEndHover() { + let btn = document.getElementById('newEntryBtn'); + btn.innerText = '+'; + } \ No newline at end of file -- cgit v1.2.3