diff --git a/js/messages.php b/js/messages.php index ec97881bad..06ae5a0eda 100644 --- a/js/messages.php +++ b/js/messages.php @@ -375,6 +375,7 @@ $js_messages['strPageName'] = __('Page name'); $js_messages['strSavePage'] = __('Save page'); $js_messages['strOpenPage'] = __('Open page'); $js_messages['strDeletePage'] = __('Delete page'); +$js_messages['strUntitled'] = __('*Untitled'); $js_messages['strSelectPage'] = __('Please select a page to continue'); $js_messages['strEnterValidPageName'] = __('Please enter a valid page name'); $js_messages['strLeavingPage'] = __('Do you want to save the changes to the current page?'); diff --git a/js/pmd/designer_db.js b/js/pmd/designer_db.js new file mode 100644 index 0000000000..4078fc6247 --- /dev/null +++ b/js/pmd/designer_db.js @@ -0,0 +1,143 @@ +var designer_tables = [{name: "pdf_pages", key: "pg_nr", auto_inc: true}, + {name: "relation", key: "rel_nr", auto_inc: true}, + {name: "table_coords", key: "id", auto_inc: true}]; + +var DesignerOfflineDB = (function () { + var designerDB = {}; + var datastore = null; + + designerDB.open = function (callback) + { + var version = 2; + var request = window.indexedDB.open("pmd_designer", version); + + request.onupgradeneeded = function (e) { + var db = e.target.result; + e.target.transaction.onerror = designerDB.onerror; + + for (var t in designer_tables) { + if (db.objectStoreNames.contains(designer_tables[t].name)) { + db.deleteObjectStore(designer_tables[t].name); + } + } + + for (var t in designer_tables) { + db.createObjectStore(designer_tables[t].name, { + keyPath: designer_tables[t].key, autoIncrement: designer_tables[t].auto_inc + }); + } + }; + + request.onsuccess = function (e) { + datastore = e.target.result; + if (callback != null) { + callback(true); + } + }; + + request.onerror = designerDB.onerror; + }; + + designerDB.loadObject = function (table, id, callback) + { + var db = datastore; + var transaction = db.transaction([table], 'readwrite'); + var objStore = transaction.objectStore(table); + var cursorRequest = objStore.get(parseInt(id)); + + cursorRequest.onsuccess = function (e) { + var result = e.target.result; + callback(result); + }; + + cursorRequest.onerror = designerDB.onerror; + }; + + designerDB.loadAllObjects = function (table, callback) + { + var db = datastore; + var transaction = db.transaction([table], 'readwrite'); + var objStore = transaction.objectStore(table); + var keyRange = IDBKeyRange.lowerBound(0); + var cursorRequest = objStore.openCursor(keyRange); + + var results = []; + + transaction.oncomplete = function (e) { + callback(results); + }; + + cursorRequest.onsuccess = function (e) { + var result = e.target.result; + + if (!!result == false) { + return; + } + results.push(result.value); + result.continue(); + }; + + cursorRequest.onerror = designerDB.onerror; + }; + + designerDB.loadFirstObject = function(table, callback) + { + var db = datastore; + var transaction = db.transaction([table], 'readwrite'); + var objStore = transaction.objectStore(table); + var keyRange = IDBKeyRange.lowerBound(0); + var cursorRequest = objStore.openCursor(keyRange); + + var firstResult = null; + + transaction.oncomplete = function(e) { + callback(firstResult); + }; + + cursorRequest.onsuccess = function(e) { + var result = e.target.result; + + if (!!result == false) { + return; + } + firstResult = result.value; + }; + + cursorRequest.onerror = designerDB.onerror; + }; + + designerDB.addObject = function(table, obj, callback) + { + var db = datastore; + var transaction = db.transaction([table], 'readwrite'); + var objStore = transaction.objectStore(table); + + var request = objStore.put(obj); + + request.onsuccess = function(e) { + callback(e.currentTarget.result); + }; + + request.onerror = designerDB.onerror; + }; + + designerDB.deleteObject = function(table, id, callback) + { + var db = datastore; + var transaction = db.transaction([table], 'readwrite'); + var objStore = transaction.objectStore(table); + + var request = objStore.delete(parseInt(id)); + + request.onsuccess = function(e) { + callback(true); + } + + request.onerror = function(e) { + console.log(e); + }; + }; + + // Export the designerDB object. + return designerDB; +}()); diff --git a/js/pmd/designer_objects.js b/js/pmd/designer_objects.js new file mode 100644 index 0000000000..09f73acc60 --- /dev/null +++ b/js/pmd/designer_objects.js @@ -0,0 +1,34 @@ +function PDFPage(db_name, page_descr, tbl_cords) +{ + if (page_descr == null) { + this.pg_nr = db_name.pg_nr; + this.db_name = db_name.db_name; + this.page_descr = db_name.page_descr; + this.tbl_cords = db_name.tbl_cords; + } else { + this.pg_nr; + this.db_name = db_name; + this.page_descr = page_descr; + this.tbl_cords = tbl_cords; + } +} + +function TableCoordinate(obj) +{ + this.id = obj.id; + this.db_name = obj.db_name; + this.table_name = obj.table_name; + this.pdf_pg_nr = obj.pdf_pg_nr; + this.x = obj.x; + this.y = obj.y; +} + +function TableCoordinate(db_name, table_name, pdf_pg_nr, x, y) +{ + this.id; + this.db_name = db_name; + this.table_name = table_name; + this.pdf_pg_nr = pdf_pg_nr; + this.x = x; + this.y = y; +} diff --git a/js/pmd/designer_page.js b/js/pmd/designer_page.js new file mode 100644 index 0000000000..bd0e3d1c6a --- /dev/null +++ b/js/pmd/designer_page.js @@ -0,0 +1,146 @@ +function Show_tables_in_landing_page() +{ + Load_first_page(function (page) { + if (page) { + Load_HTML_for_page(page.pg_nr); + selected_page = page.pg_nr; + } else { + Show_new_page_tables(true); + } + }); +} + +function Save_to_new_page(db, page_name, table_positions, callbcak) +{ + Create_new_page(db, page_name, function (page) { + if (page) { + var tbl_cords = []; + for (pos in table_positions) { + table_positions[pos].pdf_pg_nr = page.pg_nr; + Save_table_positions(table_positions[pos], function (id) { + tbl_cords.push(id); + if (table_positions.length === tbl_cords.length) { + page.tbl_cords = tbl_cords; + DesignerOfflineDB.addObject('pdf_pages', page, function() {}); + callbcak(page); + } + }); + } + } + }); +} + +function Save_to_selected_page(db, page_id, page_name, table_positions, callbcak) +{ + Delete_page(page_id, function() {}); + Save_to_new_page(db, page_name, table_positions, function (page) { + callbcak(page); + selected_page = page.pg_nr; + }); +} + +function Create_new_page(db, page_name, callback) +{ + var newPage = new PDFPage(db, page_name); + DesignerOfflineDB.addObject('pdf_pages', newPage, function (pg_nr) { + newPage.pg_nr = pg_nr; + callback(newPage); + }); +} + +function Save_table_positions(positions, callback) +{ + DesignerOfflineDB.addObject('table_coords', positions, function (id) { + callback(id); + }); +} + +function Create_page_list(callback) +{ + DesignerOfflineDB.loadAllObjects('pdf_pages', function (pages) { + var html = ""; + for( var p in pages) { + html += ''; + } + callback(html); + }); +} + +function Delete_page(page_id, callback) +{ + DesignerOfflineDB.loadObject('pdf_pages', page_id, function (page) { + if (page) { + for (i in page.tbl_cords) { + DesignerOfflineDB.deleteObject('table_coords', page.tbl_cords[i], function() {}); + } + DesignerOfflineDB.deleteObject('pdf_pages', page_id, function (state) { + callback(state); + }); + } + }); +} + +function Load_first_page(callback) +{ + DesignerOfflineDB.loadFirstObject('pdf_pages', function (page) { + callback(page); + }); +} + +function Show_new_page_tables(check) +{ + var all_tables = $("#id_scroll_tab td input:checkbox"); + all_tables.prop('checked', check); + for (var tab in all_tables) { + var input = all_tables[tab]; + if (input.value) { + VisibleTab(input, input.value); + var element = document.getElementById(input.value); + element.style.top = Get_random(550, 20) + 'px'; + element.style.left = Get_random(700, 20) + 'px'; + } + } + selected_page = -1; + $("#top_menu #page_name").html(PMA_messages.strUntitled); +} + +function Load_HTML_for_page(page_id) +{ + Show_new_page_tables(false); + Load_page_objects(page_id, function (page, tbl_cords) { + $("#top_menu #page_name").html(page.page_descr); + for (var t in tbl_cords) { + var tb_id = db + '.' + tbl_cords[t].table_name; + var table = document.getElementById(tb_id); + table.style.top = tbl_cords[t].y + 'px'; + table.style.left = tbl_cords[t].x + 'px'; + + var checkbox = document.getElementById("check_vis_" + tb_id); + checkbox.checked = true; + VisibleTab(checkbox, checkbox.value); + } + selected_page = page.pg_nr; + }); +} + +function Load_page_objects(page_id, callback) +{ + DesignerOfflineDB.loadObject('pdf_pages', page_id, function (page) { + var tbl_cords = []; + for (i in page.tbl_cords) { + DesignerOfflineDB.loadObject('table_coords', page.tbl_cords[i], function (tbl_cord) { + tbl_cords.push(tbl_cord); + if (tbl_cords.length === page.tbl_cords.length) { + callback(page,tbl_cords); + } + }); + } + }); +} + +function Get_random(max, min) +{ + var val = Math.random() * (max - min) + min; + return Math.floor(val); +} \ No newline at end of file diff --git a/js/pmd/init.js b/js/pmd/init.js index 9c6b4919bf..7adfca5a5c 100644 --- a/js/pmd/init.js +++ b/js/pmd/init.js @@ -3,7 +3,7 @@ * Initialises the data required to run PMD, then fires it up. */ -var j_tabs, h_tabs, contr, server, db, token, selected_page; +var j_tabs, h_tabs, contr, server, db, token, selected_page, pmd_tables_enabled; AJAX.registerTeardown('pmd/init.js', function () { $(".trigger").unbind('click'); @@ -15,18 +15,26 @@ AJAX.registerOnload('pmd/init.js', function () { $(this).toggleClass("active"); return false; }); - var tables_data = $.parseJSON($("#script_tables").html()); - j_tabs = tables_data.j_tabs; - h_tabs = tables_data.h_tabs; - contr = $.parseJSON($("#script_contr").html()); - display_field = $.parseJSON($("#script_display_field").html()); + j_tabs = tables_data.j_tabs; + h_tabs = tables_data.h_tabs; + contr = $.parseJSON($("#script_contr").html()); + display_field = $.parseJSON($("#script_display_field").html()); - server = $("#script_server").html(); - db = $("#script_db").html(); - token = $("#script_token").html(); - selected_page = $("#script_display_page").html(); + server = $("#script_server").html(); + db = $("#script_db").html(); + token = $("#script_token").html(); + selected_page = $("#script_display_page").html() === "" ? "-1" : $("#script_display_page").html(); + pmd_tables_enabled = $("#pmd_tables_enabled").html() === "1"; Main(); + + if (! pmd_tables_enabled) { + DesignerOfflineDB.open(function(success) { + if (success) { + Show_tables_in_landing_page(); + } + }); + } }); diff --git a/js/pmd/move.js b/js/pmd/move.js index 9fa344904e..63cc90d2ce 100644 --- a/js/pmd/move.js +++ b/js/pmd/move.js @@ -541,30 +541,52 @@ function Save(url) // (del?) no for pdf function Get_url_pos() { - var poststr = ''; - for (var key in j_tabs) { - poststr += '&t_x[' + key + ']=' + parseInt(document.getElementById(key).style.left, 10); - poststr += '&t_y[' + key + ']=' + parseInt(document.getElementById(key).style.top, 10); - poststr += '&t_v[' + key + ']=' + (document.getElementById('id_tbody_' + key).style.display == 'none' ? 0 : 1); - poststr += '&t_h[' + key + ']=' + (document.getElementById('check_vis_' + key).checked ? 1 : 0); + if (pmd_tables_enabled) { + var poststr = ''; + for (var key in j_tabs) { + poststr += '&t_x[' + key + ']=' + parseInt(document.getElementById(key).style.left, 10); + poststr += '&t_y[' + key + ']=' + parseInt(document.getElementById(key).style.top, 10); + poststr += '&t_v[' + key + ']=' + (document.getElementById('id_tbody_' + key).style.display == 'none' ? 0 : 1); + poststr += '&t_h[' + key + ']=' + (document.getElementById('check_vis_' + key).checked ? 1 : 0); + } + return poststr; + } else { + var coords = []; + for (var key in j_tabs) { + if (document.getElementById('check_vis_' + key).checked) { + var x = parseInt(document.getElementById(key).style.left, 10); + var y = parseInt(document.getElementById(key).style.top, 10); + var tbCoords = new TableCoordinate(db, key.split(".")[1], -1, x, y); + coords.push(tbCoords); + } + } + return coords; } - return poststr; } function Save2(callback) { _change = 0; - var poststr = 'IS_AJAX=1&server=' + server + '&db=' + db + '&token=' + token + '&die_save_pos=1&selected_page=' + selected_page; - poststr += Get_url_pos(); - makeRequest('pmd_save_pos.php', poststr); - if (callback != null) { - callback(); + if (pmd_tables_enabled) { + var poststr = 'IS_AJAX=1&server=' + server + '&db=' + db + '&token=' + token + '&die_save_pos=1&selected_page=' + selected_page; + poststr += Get_url_pos(); + makeRequest('pmd_save_pos.php', poststr); + if (callback != null) { + callback(); + } + } else { + var name = $("#page_name").html().trim(); + Save_to_selected_page(db, selected_page, name, Get_url_pos(), function (page){ + if (callback != null) { + callback(); + } + }); } } function Save3(callback) { - if (selected_page !== '-1') { + if (parseInt(selected_page) !== -1) { Save2(callback); } else { var button_options = {}; @@ -577,23 +599,37 @@ function Save3(callback) } $(this).dialog('close'); - var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); - PMA_prepareForAjaxRequest($form); - $.post($form.attr('action'), $form.serialize() + Get_url_pos(), function (data) { - if (data.success === false) { - PMA_ajaxShowMessage(data.error, false); - } else { - PMA_ajaxRemoveMessage($msgbox); - _change = 0; - if (data.id) { - selected_page = data.id; + if (pmd_tables_enabled) { + var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); + PMA_prepareForAjaxRequest($form); + $.post($form.attr('action'), $form.serialize() + Get_url_pos(), function (data) { + if (data.success === false) { + PMA_ajaxShowMessage(data.error, false); + } else { + PMA_ajaxRemoveMessage($msgbox); + _change = 0; + if (data.id) { + selected_page = data.id; + } + $('#page_name').text(name); + if (callback != null) { + callback(); + } } - $('#page_name').text(name); + }); + } else { + Save_to_new_page(db, name, Get_url_pos(), function (page) { + _change = 0; + debugger; + if (page.pg_nr) { + selected_page = page.pg_nr; + } + $('#page_name').text(page.page_descr); if (callback != null) { callback(); } - } - }); // end $.post() + }); + } }; button_options[PMA_messages.strCancel] = function () { $(this).dialog('close'); @@ -647,6 +683,12 @@ function Edit_pages() PMA_ajaxShowMessage(data.error, false); } else { PMA_ajaxRemoveMessage($msgbox); + + if (! pmd_tables_enabled) { + Create_page_list(function (options) { + $("#page_edit_dialog #selected_page").append(options); + }); + } $('
') .append(data.message) .dialog({ @@ -675,20 +717,36 @@ function Delete_pages() } var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); - var deleting_current_page = selected === selected_page; + var deleting_current_page = selected == selected_page; PMA_prepareForAjaxRequest($form); - $.post($form.attr('action'), $form.serialize(), function (data) { - if (data.success === false) { - PMA_ajaxShowMessage(data.error, false); - } else { - PMA_ajaxRemoveMessage($msgbox); - if (deleting_current_page) { - Load_page(null); + + if (pmd_tables_enabled) { + $.post($form.attr('action'), $form.serialize(), function (data) { + if (data.success === false) { + PMA_ajaxShowMessage(data.error, false); } else { - PMA_ajaxShowMessage(PMA_messages.strSuccessfulPageDelete); + PMA_ajaxRemoveMessage($msgbox); + if (deleting_current_page) { + Load_page(null); + } else { + PMA_ajaxShowMessage(PMA_messages.strSuccessfulPageDelete); + } } - } - }); // end $.post() + }); // end $.post() + } else { + Delete_page(selected, function (success) { + if (! success) { + PMA_ajaxShowMessage("Error", false); + } else { + PMA_ajaxRemoveMessage($msgbox); + if (deleting_current_page) { + Load_page(null); + } else { + PMA_ajaxShowMessage(PMA_messages.strSuccessfulPageDelete); + } + } + }); + } $(this).dialog('close'); }; @@ -703,6 +761,13 @@ function Delete_pages() PMA_ajaxShowMessage(data.error, false); } else { PMA_ajaxRemoveMessage($msgbox); + + if (! pmd_tables_enabled) { + Create_page_list(function (options) { + $("#page_delete_dialog #selected_page").append(options); + }); + } + $('') .append(data.message) .dialog({ @@ -744,19 +809,42 @@ function Save_as() } var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); - PMA_prepareForAjaxRequest($form); - $.post($form.attr('action'), $form.serialize() + Get_url_pos(), function (data) { - if (data.success === false) { - PMA_ajaxShowMessage(data.error, false); - } else { - PMA_ajaxRemoveMessage($msgbox); - _change = 0; - if (data.id) { - selected_page = data.id; + if (pmd_tables_enabled) { + PMA_prepareForAjaxRequest($form); + $.post($form.attr('action'), $form.serialize() + Get_url_pos(), function (data) { + if (data.success === false) { + PMA_ajaxShowMessage(data.error, false); + } else { + PMA_ajaxRemoveMessage($msgbox); + _change = 0; + if (data.id) { + selected_page = data.id; + } + $('#page_name').text(name); } - $('#page_name').text(name); + }); // end $.post() + } else { + if (choice === 'same') { + var selected_page_id = $selected_page.find('option:selected').val(); + Save_to_selected_page(db, selected_page_id, name, Get_url_pos(), function (page) { + PMA_ajaxRemoveMessage($msgbox); + _change = 0; + if (page.pg_nr) { + selected_page = page.pg_nr; + } + $('#page_name').text(page.page_descr); + }); + } else if (choice === 'new') { + Save_to_new_page(db, name, Get_url_pos(), function (page) { + PMA_ajaxRemoveMessage($msgbox); + _change = 0; + if (page.pg_nr) { + selected_page = page.pg_nr; + } + $('#page_name').text(page.page_descr); + }); } - }); // end $.post() + } $(this).dialog('close'); }; @@ -771,6 +859,13 @@ function Save_as() PMA_ajaxShowMessage(data.error, false); } else { PMA_ajaxRemoveMessage($msgbox); + + if (! pmd_tables_enabled) { + Create_page_list(function (options) { + $("#page_save_as_dialog #selected_page").append(options); + }); + } + $('') .append(data.message) .dialog({ @@ -828,7 +923,7 @@ function Export_pages() button_options[PMA_messages.strGo] = function () { var $form = $("#id_export_pages"); var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); - location.href = $form.attr('action') + '?' + getParamsForExport($form) + Get_url_pos(); + location.href = $form.attr('action') + '?' + getParamsForExport($form); $msgbox.remove(); $(this).dialog('close'); }; @@ -873,19 +968,35 @@ function getParamsForExport($from) url += "&show_grid=" + ($from.find('input[name="show_grid"]').is(":checked") ? "on" : "off"); url += "&show_keys=" + ($from.find('input[name="show_keys"]').is(":checked") ? "on" : "off"); url += "&show_table_dimension=" + ($from.find('input[name="show_table_dimension"]').is(":checked") ? "on" : "off"); + url += "&offline_export=" + (pmd_tables_enabled ? "off" : "on"); + if (pmd_tables_enabled) { + url += Get_url_pos(); + } else { + url += "&tbl_coords=" + JSON.stringify(Get_url_pos()); + } return url; } function Load_page(page) { - var param_page = ''; - if (page != null) { - param_page = '&page=' + page; + if (pmd_tables_enabled) { + var param_page = ''; + if (page != null) { + param_page = '&page=' + page; + } + $('') + .appendTo($('#page_content')) + .click(); + } else { + if (page == null) { + Show_tables_in_landing_page(); + } else if (page > -1) { + Load_HTML_for_page(page); + } else if (page === -1) { + Show_new_page_tables(true); + } } - $('') - .appendTo($('#page_content')) - .click(); _change = 0; } @@ -1608,4 +1719,4 @@ function add_object() existingDiv.innerHTML = display(init, history_array.length); Close_option(); panel(0); -} +} \ No newline at end of file diff --git a/libraries/Menu.class.php b/libraries/Menu.class.php index 5e1cf4a9b6..ea82fc6877 100644 --- a/libraries/Menu.class.php +++ b/libraries/Menu.class.php @@ -471,11 +471,11 @@ class PMA_Menu $tabs['tracking']['link'] = 'db_tracking.php'; } - if (! $db_is_system_schema && $cfgRelation['pdfwork']) { - $tabs['designer']['text'] = __('Designer'); - $tabs['designer']['icon'] = 'b_relations.png'; - $tabs['designer']['link'] = 'pmd_general.php'; - } + $tabs['designer']['text'] = __('Designer'); + $tabs['designer']['icon'] = 'b_relations.png'; + $tabs['designer']['link'] = 'pmd_general.php'; + $tabs['designer']['id'] = 'designer_tab'; + if (! $db_is_system_schema && $cfgRelation['central_columnswork']) { $tabs['central_columns']['text'] = __('Central columns'); $tabs['central_columns']['icon'] = 'centralColumns.png'; diff --git a/libraries/designer.lib.php b/libraries/designer.lib.php index ad6689721a..880285a62e 100644 --- a/libraries/designer.lib.php +++ b/libraries/designer.lib.php @@ -21,6 +21,7 @@ require_once 'libraries/relation.lib.php'; */ function PMA_getHtmlForEditOrDeletePages($db, $operation) { + $cfgRelation = PMA_getRelationsParam(); $html = '