diff --git a/js/message.js b/js/message.js deleted file mode 100644 index e064ac5..0000000 --- a/js/message.js +++ /dev/null @@ -1,100 +0,0 @@ -class Message { - timer; - - constructor() { - this.div = $('
'); - this.div.css({ - "position": "absolute", - "top": "10px", - "right": "20px", - "z-index": "1000" - }); - - $('body').append(this.div); - } - - success(message, delay = 6000) { - this.print(message, delay, '#52b818', '#bffdc0'); - } - - warning(message, delay = 6000) { - this.print(message, delay, '#b8ae18', '#f8fdbf'); - } - - error(message, delay = 6000) { - this.print(message, delay, '#b96161', '#fddede'); - } - - print = function(message, delay, border, background) { - if (delay < 6000) delay = 6000; - let Timer = function(callback, delay) { - let timerId, start, remaining = delay; - - this.pause = function() { - clearTimeout(timerId); - remaining -= new Date() - start; - }; - - this.resume = function() { - start = new Date(); - clearTimeout(timerId); - timerId = setTimeout(callback, remaining); - }; - - this.dead = function() { - clearTimeout(timerId); - }; - - this.resume(); - } - - let newMessage = $(`
${message}
`); - - newMessage.css({ - "border": `1px solid ${border}`, - "background-color": `${background}`, - "color": "#333", - "padding": "10px 30px", - "text-align": "center", - "display": "none", - "margin": "10px 0 0 0", - "width": "350px", - "opacity": "1", - "cursor": "pointer" - }); - - newMessage.hover(function(){ - $(this).css({ - "opacity": "1" - }); - }, function(){ - $(this).css({ - "opacity": "0.3" - }); - }); - - this.div.append(newMessage); - - let opacityTimeout = setTimeout(function() { - newMessage.fadeTo(1000, 0.3); - }, 2500); - - newMessage.fadeIn(500).mouseenter(() => { - clearTimeout(opacityTimeout); - this.timer.pause(); - }).mouseleave(() => { - this.timer.resume(); - }).click(() => { - this.timer.dead(); - newMessage.fadeOut(0, function(){ - this.remove(); - }); - }); - - this.timer = new Timer(() => { - newMessage.fadeOut(500, function(){ - this.remove(); - }); - }, delay); - } -} diff --git a/js/noticer.min.js b/js/noticer.min.js new file mode 100644 index 0000000..e9e9957 --- /dev/null +++ b/js/noticer.min.js @@ -0,0 +1,4 @@ +/*! noticer - v0.1.0 - 2023-05-31 +* https://git.zhirov.kz/alexander/noticer +* Copyright Alexander Zhirov; Licensed GPL-2.0 */ +class Noticer{timer;constructor(){this.div=$('
'),this.div.css({position:"absolute",top:"10px",right:"20px","z-index":"1000"}),$("body").append(this.div)}success(e,t=6e3){this.print(e,t,"#52b818","#bffdc0")}warning(e,t=6e3){this.print(e,t,"#b8ae18","#f8fdbf")}error(e,t=6e3){this.print(e,t,"#b96161","#fddede")}print=function(e,t,n,s){t<6e3&&(t=6e3);let i=function(e,t){let n,s,o=t;this.pause=function(){clearTimeout(n),o-=new Date-s},this.resume=function(){s=new Date,clearTimeout(n),n=setTimeout(e,o)},this.dead=function(){clearTimeout(n)},this.resume()},o=$(`
${e}
`);o.css({border:`1px solid ${n}`,"background-color":`${s}`,color:"#333",padding:"10px 30px","text-align":"center",display:"none",margin:"10px 0 0 0",width:"350px",opacity:"1",cursor:"pointer"}),o.hover(function(){$(this).css({opacity:"1"})},function(){$(this).css({opacity:"0.3"})}),this.div.append(o);let a=setTimeout(function(){o.fadeTo(1e3,.3)},2500);o.fadeIn(500).mouseenter(()=>{clearTimeout(a),this.timer.pause()}).mouseleave(()=>{this.timer.resume()}).click(()=>{this.timer.dead(),o.fadeOut(0,function(){this.remove()})}),this.timer=new i(()=>{o.fadeOut(500,function(){this.remove()})},t)}} diff --git a/js/script.js b/js/script.js index 711df54..845d167 100644 --- a/js/script.js +++ b/js/script.js @@ -1,7 +1,7 @@ var numbers = []; $(document).ready(function () { - message = new Message; + noticer = new Noticer; $("button").button(); $("#tabs").tabs(); @@ -59,9 +59,9 @@ function isJSON(str) { function loadData() { request('listsgroups', 'text').then(data => { - data.error ? message.error(data.message) : generateListsGroups(data); + data.error ? noticer.error(data.message) : generateListsGroups(data); }).catch(error => { - message.error(error.message); + noticer.error(error.message); }); } @@ -78,16 +78,16 @@ function generateListsGroups(data) { }); } -async function generateGroupNumbers(panel) { +function generateGroupNumbers(panel) { request('groupnumbers', 'json', { group: panel.data("group-name") }).then(data => { if (isJSON(data) && JSON.parse(data).error) - message.error(JSON.parse(data).message); + noticer.error(JSON.parse(data).message); else { numbers = data; showNumbers(panel); } }).catch(error => { - message.error(error.message); + noticer.error(error.message); }); } @@ -95,7 +95,7 @@ function showNumbers(panel, data = numbers) { (new divNotFoundNumbers).remove(); let body = panel.find('.body').html(''); $(data).each((i, j) => { - let row = $(``); + let row = $(``); row.append(`${j.number}`); row.append(`${j.list}`); row.append(`${j.all_cc}`); @@ -104,8 +104,8 @@ function showNumbers(panel, data = numbers) { row.append(`${j.comment}`); body.append(row); - row.click(function(){ - // numberEdit($(this).data('number')); + row.click(function() { + numberEdit($(this).data('number')); }); }); @@ -133,3 +133,75 @@ function divNotFoundNumbers() { notFound.remove(); } } + +function numberEdit(number) { + request('editnumber', 'text', {number: number}).then(data => { + if (isJSON(data) && JSON.parse(data).error) + noticer.error(JSON.parse(data).message); + else { + showEditNumber(data, [ + { + id: "btn-save", + text: "Сохранить", + icon: "ui-icon-check", + click: function() { + actionNumber($(this), 'update'); + } + }, + { + id: "btn-delete", + text: "Удалить", + icon: "ui-icon-trash", + click: function() { + // removeNumber($(this)); + } + } + ], `Редактирование номера ${number}`); + } + }).catch(error => { + noticer.error(error.message); + }); +} + +function showEditNumber(data, actionButton, title) { + let form = $(data); + + form.appendTo('body').dialog({ + title: title, + height: 'auto', + width: 'auto', + maxHeight: 500, + minHeight: 50, + resizable: false, + modal: true, + show: { effect: "fade", duration: 500 }, + close: function(event, ui) { + $(this).dialog('destroy').remove() + }, + buttons: [ + ...actionButton, + { + text: "Отмена", + icon: "ui-icon-cancel", + click: function() { + $(this).dialog("close"); + } + } + ] + }); + + $('#number-group, #number-list').selectmenu({ + width: 200 + }); +} + +function actionNumber(currentWindow, query) { + let number = $('#number-number').val(); + let group = $('#number-group').val(); + let list = $('#number-list').val(); + let all_cc = $('#number-all-cc').val(); + let white_cc = $('#number-white-cc').val(); + let black_cc = $('#number-black-cc').val(); + let comment = $('#number-comment').val(); +} + diff --git a/public/style.css b/public/style.css index 3f86680..767e236 100644 --- a/public/style.css +++ b/public/style.css @@ -49,18 +49,19 @@ input { border: 1px solid#c5c5c5; } -.input-focus:hover { - border: 1px solid #ccc +.input-focus:hover:not([disabled]) { + border: 1px solid #999; + box-shadow: 1px 1px 10px 1px #ccc; } .input-focus::placeholder { color: #333 } -.input-focus:focus { +.input-focus:focus:not([disabled]) { outline: none; - box-shadow: 1px 1px 10px 1px #007fff; - border: 1px solid #003eff; + box-shadow: 1px 1px 10px 1px #666; + border: 1px solid #555; } /* BODY */ @@ -96,6 +97,12 @@ td { text-align: center; } +.body-rows td { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + .body-rows tbody tr:nth-child(even){ background: #fff; } @@ -105,3 +112,48 @@ tr.row:hover, tr.row:nth-child(even):hover { color: #fff; cursor: pointer; } + +/* EDIT NUMBER */ + +.number-label { + color: #333; + text-align: right; +} + +.number-value { + height: 30px; +} + +.number-input-main { + height: 25px; + width: 194px; + margin: 0 10px 0 10px; +} + +.number-input-cc { + height: 25px; + width: 50px; + margin: 0 10px 0 10px; +} + +.div-advanced { + display: flex; + flex-direction: column; +} + +.comment { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.comment-content { + width: 100%; + height: 100%; +} + +#number-comment { + width: calc(100% - 6px); + resize: none; +} diff --git a/source/daster.d b/source/daster.d index 7c2c52a..14a7121 100644 --- a/source/daster.d +++ b/source/daster.d @@ -18,6 +18,7 @@ import structures; import requests.listsgroups; import requests.groupnumbers; +import requests.editnumber; static ServerInfo serverInfo; @@ -169,10 +170,10 @@ void postReq(HTTPServerRequest req, HTTPServerResponse res) { switch (query) { case "listsgroups": - listsgroups(req, res); + listsGroups(req, res); break; case "groupnumbers": - groupnumbers(req, res); + groupNumbers(req, res); break; // case "authorization": // authorization(req, res); @@ -189,9 +190,9 @@ void postReq(HTTPServerRequest req, HTTPServerResponse res) { // case "write": // writeNumber(req, res); // break; - // case "edit": - // editNumber(req, res); - // break; + case "editnumber": + editNumber(req, res); + break; // case "update": // updateNumber(req, res); // break; diff --git a/source/data.d b/source/data.d index b333388..0b6eaaa 100644 --- a/source/data.d +++ b/source/data.d @@ -11,10 +11,10 @@ GroupDB[] getListGroups() { try { auto queryResult = pgsql.sql( "select distinct - n.da_group, - g.da_comment - from da_numbers n - left join da_groups g ON g.da_name = n.da_group" + dan.da_group, + dag.da_comment + from da_numbers dan + left join da_groups dag ON dag.da_name = dan.da_group" ); foreach (row; queryResult) { GroupDB data; @@ -43,8 +43,8 @@ NumberDB[] getListNumbers(string group) { dan.da_black_cc, dan.da_comment from da_numbers dan - left join da_lists dal on dal.da_name = dan.da_list - where da_group = ?", + left join da_lists dal on dal.da_name = dan.da_list + where dan.da_group = ?", group ); foreach (row; queryResult) { @@ -65,3 +65,77 @@ NumberDB[] getListNumbers(string group) { return numbers; } + +NumberDB getDataNumber(string number) { + NumberDB data; + try { + auto queryResult = pgsql.sql( + "select + da_number, + da_group, + da_list, + da_all_cc, + da_white_cc, + da_black_cc, + da_comment + from da_numbers + where da_number = ?", + number + ); + foreach (row; queryResult) { + data.number = row["da_number"]; + data.group = row["da_group"]; + data.list = row["da_list"]; + data.all_cc = row["da_all_cc"].to!int; + data.white_cc = row["da_white_cc"].to!int; + data.black_cc = row["da_black_cc"].to!int; + data.comment = row["da_comment"]; + } + } catch (Exception e) { + log.e("Не удалось выполнить запрос к БД. " ~ e.msg); + } + + return data; +} + +GroupDB[] getGroups() { + GroupDB[] groups; + try { + auto queryResult = pgsql.sql( + "select da_name, da_comment from da_groups" + ); + foreach (row; queryResult) { + GroupDB data; + + data.name = row["da_name"]; + data.comment = row["da_comment"]; + + groups ~= data; + } + } catch (Exception e) { + log.e("Не удалось выполнить запрос к БД. " ~ e.msg); + } + + return groups; +} + +ListDB[] getLists() { + ListDB[] lists; + try { + auto queryResult = pgsql.sql( + "select da_name, da_comment from da_lists" + ); + foreach (row; queryResult) { + ListDB data; + + data.name = row["da_name"]; + data.comment = row["da_comment"]; + + lists ~= data; + } + } catch (Exception e) { + log.e("Не удалось выполнить запрос к БД. " ~ e.msg); + } + + return lists; +} diff --git a/source/requests/editnumber.d b/source/requests/editnumber.d new file mode 100644 index 0000000..4d8be89 --- /dev/null +++ b/source/requests/editnumber.d @@ -0,0 +1,15 @@ +module requests.editnumber; + +import vibe.vibe; +import response; +import data; +import singlog; + +void editNumber(HTTPServerRequest req, HTTPServerResponse res) { + auto jsr = req.json; + bool edit = true; + auto dataNumber = getDataNumber(jsr["number"].get!string); + auto groups = getGroups(); + auto lists = getLists(); + render!("edit-number.dt", edit, dataNumber, groups, lists)(res); +} diff --git a/source/requests/groupnumbers.d b/source/requests/groupnumbers.d index 62f6288..1d7f73a 100644 --- a/source/requests/groupnumbers.d +++ b/source/requests/groupnumbers.d @@ -5,7 +5,7 @@ import response; import data; import singlog; -void groupnumbers(HTTPServerRequest req, HTTPServerResponse res) { +void groupNumbers(HTTPServerRequest req, HTTPServerResponse res) { auto jsr = req.json; res.writeJsonBody(getListNumbers(jsr["group"].get!string).serializeToJson()); } diff --git a/source/requests/listsgroups.d b/source/requests/listsgroups.d index 4d6bec3..94e6dbb 100644 --- a/source/requests/listsgroups.d +++ b/source/requests/listsgroups.d @@ -4,7 +4,7 @@ import vibe.vibe; import response; import data; -void listsgroups(HTTPServerRequest req, HTTPServerResponse res) { +void listsGroups(HTTPServerRequest req, HTTPServerResponse res) { auto listGroups = getListGroups(); render!("group-numbers-list.dt", listGroups)(res); } diff --git a/source/structures.d b/source/structures.d index 1f04a77..a115318 100644 --- a/source/structures.d +++ b/source/structures.d @@ -22,6 +22,11 @@ struct GroupDB { string comment; } +struct ListDB { + string name; + string comment; +} + struct NumberDB { string number; string group; diff --git a/views/edit-number.dt b/views/edit-number.dt new file mode 100644 index 0000000..fd8c788 --- /dev/null +++ b/views/edit-number.dt @@ -0,0 +1,43 @@ +- import structures; +div#number-data + table + tbody + tr + td.number-label Номер: + td.number-value + - if (edit) + input.number-input-main.input-focus#number-number(type='text', value='#{dataNumber.number}', disabled) + - else + input.number-input-main.input-focus#number-number(type='text', value='#{dataNumber.number}') + td.number-label Общие звонки: + td.number-value + input.number-input-cc.input-focus#number-all-cc(type='text', value='#{dataNumber.all_cc}') + tr + td.number-label Группа: + td.number-value + select#number-group + - foreach (group; groups) + - if (dataNumber.group == group.name) + option(selected, value='#{group.name}') #{group.comment} + - else + option(value='#{group.name}') #{group.comment} + td.number-label Белые звонки: + td.number-value + input.number-input-cc.input-focus#number-white-cc(type='text', value='#{dataNumber.white_cc}') + tr + td.number-label Список: + td.number-value + select#number-list + - foreach (list; lists) + - if (dataNumber.list == list.name) + option(selected, value='#{list.name}') #{list.comment} + - else + option(value='#{list.name}') #{list.comment} + td.number-label Черные звонки: + td.number-value + input.number-input-cc.input-focus#number-black-cc(type='text', value='#{dataNumber.black_cc}') + div.div-advanced + div.comment + div.comment-name Комментарий + div.comment-content + textarea.input-focus#number-comment #{dataNumber.comment} diff --git a/views/index.dt b/views/index.dt index 69887bd..e32e093 100644 --- a/views/index.dt +++ b/views/index.dt @@ -6,7 +6,7 @@ head link(rel='stylesheet', type='text/css', href='style.css') script(src='jquery-3.7.0.min.js') script(src='jquery-ui.min.js') - script(src='message.js') + script(src='noticer.min.js') script(src='script.js') body div.div-header