diff options
Diffstat (limited to 'srcs/phpmyadmin/templates/table')
31 files changed, 2680 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig b/srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig new file mode 100644 index 0000000..f2ec2ba --- /dev/null +++ b/srcs/phpmyadmin/templates/table/browse_foreigners/column_element.twig @@ -0,0 +1,12 @@ +<td{{ nowrap ? ' class="nowrap"' }}> + {{ is_selected ? '<strong>' }} + <a class="foreign_value" data-key="{{ keyname }}" href="#" title=" + {%- trans 'Use this value' %}{{ title is not empty ? ': ' ~ title }}"> + {% if nowrap %} + {{ keyname }} + {% else %} + {{ description }} + {% endif %} + </a> + {{ is_selected ? '</strong>' }} +</td> diff --git a/srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig b/srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig new file mode 100644 index 0000000..4de9b81 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/browse_foreigners/show_all.twig @@ -0,0 +1,5 @@ +{% if foreign_data.disp_row is iterable and + (show_all and foreign_data.the_total > max_rows) %} + <input class="btn btn-secondary" type="submit" id="foreign_showAll" name="foreign_showAll" value=" + {%- trans 'Show all' %}"> +{% endif %} diff --git a/srcs/phpmyadmin/templates/table/chart/tbl_chart.twig b/srcs/phpmyadmin/templates/table/chart/tbl_chart.twig new file mode 100644 index 0000000..4201599 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/chart/tbl_chart.twig @@ -0,0 +1,159 @@ +<script type="text/javascript"> + url_query = '{{ url_query }}'; +</script> +{# Display Chart options #} +<div id="div_view_options"> + <form method="post" id="tblchartform" action="tbl_chart.php" class="ajax"> + {{ get_hidden_inputs(url_params) }} + <fieldset> + <legend> + {% trans 'Display chart' %} + </legend> + <div class="chartOption"> + <div class="formelement"> + <input type="radio" name="chartType" value="bar" id="radio_bar"> + <label for ="radio_bar">{% trans %}Bar{% context %}Chart type{% endtrans %}</label> + </div> + <div class="formelement"> + <input type="radio" name="chartType" value="column" id="radio_column"> + <label for ="radio_column">{% trans %}Column{% context %}Chart type{% endtrans %}</label> + </div> + <div class="formelement"> + <input type="radio" name="chartType" value="line" id="radio_line" checked="checked"> + <label for ="radio_line">{% trans %}Line{% context %}Chart type{% endtrans %}</label> + </div> + <div class="formelement"> + <input type="radio" name="chartType" value="spline" id="radio_spline"> + <label for ="radio_spline">{% trans %}Spline{% context %}Chart type{% endtrans %}</label> + </div> + <div class="formelement"> + <input type="radio" name="chartType" value="area" id="radio_area"> + <label for ="radio_area">{% trans %}Area{% context %}Chart type{% endtrans %}</label> + </div> + <span class="span_pie hide"> + <input type="radio" name="chartType" value="pie" id="radio_pie"> + <label for ="radio_pie">{% trans %}Pie{% context %}Chart type{% endtrans %}</label> + </span> + <span class="span_timeline hide"> + <input type="radio" name="chartType" value="timeline" id="radio_timeline"> + <label for ="radio_timeline">{% trans %}Timeline{% context %}Chart type{% endtrans %}</label> + </span> + <span class="span_scatter hide"> + <input type="radio" name="chartType" value="scatter" id="radio_scatter"> + <label for ="radio_scatter">{% trans %}Scatter{% context %}Chart type{% endtrans %}</label> + </span> + <br><br> + <span class="barStacked hide"> + <input type="checkbox" name="barStacked" value="1" id="checkbox_barStacked"> + <label for ="checkbox_barStacked">{% trans 'Stacked' %}</label> + </span> + <br><br> + <label for ="chartTitle">{% trans 'Chart title:' %}</label> + <input type="text" name="chartTitle" id="chartTitle"> + </div> + {% set xaxis = null %} + <div class="chartOption"> + <label for="select_chartXAxis">{% trans 'X-Axis:' %}</label> + <select name="chartXAxis" id="select_chartXAxis"> + {% for idx, key in keys %} + {% if xaxis is same as(null) %} + {% set xaxis = idx %} + {% endif %} + {% if xaxis is same as(idx) %} + <option value="{{ idx }}" selected="selected">{{ key }}</option> + {% else %} + <option value="{{ idx }}">{{ key }}</option> + {% endif %} + {% endfor %} + </select> + <br> + <label for="select_chartSeries"> + {% trans 'Series:' %} + </label> + <select name="chartSeries" id="select_chartSeries" multiple="multiple"> + {% for idx, key in keys %} + {% if fields_meta[idx].type in numeric_types %} + {% if idx == xaxis and numeric_column_count > 1 %} + <option value="{{ idx }}">{{ key }}</option> + {% else %} + <option value="{{ idx }}" selected="selected">{{ key }}</option> + {% endif %} + {% endif %} + {% endfor %} + </select> + <input type="hidden" name="dateTimeCols" value=" + {% set date_time_types = ['date', 'datetime', 'timestamp'] %} + {% for idx, key in keys %} + {% if fields_meta[idx].type in date_time_types %} + {{ idx ~ ' ' }} + {% endif %} + {% endfor %}"> + <input type="hidden" name="numericCols" value=" + {% for idx, key in keys %} + {% if fields_meta[idx].type in numeric_types %} + {{ idx ~ ' ' }} + {% endif %} + {% endfor %}"> + </div> + <div class="chartOption"> + <label for="xaxis_panel"> + {% trans 'X-Axis label:' %} + </label> + <input style="margin-top:0;" type="text" name="xaxis_label" id="xaxis_label" value="{{ xaxis == -1 ? 'X Values'|trans : keys[xaxis] }}"> + <br> + <label for="yaxis_label"> + {% trans 'Y-Axis label:' %} + </label> + <input type="text" name="yaxis_label" id="yaxis_label" value="{% trans 'Y Values' %}"> + <br> + </div> + <div class="clearfloat"></div> + <div> + <input type="checkbox" id="chkAlternative" name="chkAlternative" value="alternativeFormat"> + <label for="chkAlternative">{% trans 'Series names are in a column' %}</label> + <br> + <label for="select_seriesColumn"> + {% trans 'Series column:' %} + </label> + <select name="chartSeriesColumn" id="select_seriesColumn" disabled> + {% for idx, key in keys %} + <option value="{{ idx }}" + {% if idx == 1 %} + selected="selected" + {% endif %}> + {{ key }} + </option> + {% set series_column = idx %} + {% endfor %} + </select> + <label for="select_valueColumn"> + {% trans 'Value Column:' %} + </label> + <select name="chartValueColumn" id="select_valueColumn" disabled> + {% set selected = false %} + {% for idx, key in keys %} + {% if fields_meta[idx].type in numeric_types %} + {% if not selected and idx != xaxis and idx != series_column %} + <option value="{{ idx }}" selected="selected">{{ key }}</option> + {% set selected = true %} + {% else %} + <option value="{{ idx }}">{{ key }}</option> + {% endif %} + {% endif %} + {% endfor %} + </select> + </div> + {{ get_start_and_number_of_rows_panel(sql_query) }} + <div class="clearfloat"></div> + <div id="resizer" style="width:600px; height:400px;"> + <div style="position: absolute; right: 10px; top: 10px; cursor: pointer; z-index: 1000;"> + <a class="disableAjax" id="saveChart" href="#" download="chart.png"> + {{ get_image('b_saveimage', 'Save chart as image'|trans) }} + </a> + </div> + <div id="querychart" dir="ltr"> + </div> + </div> + </fieldset> + </form> +</div> diff --git a/srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig b/srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig new file mode 100644 index 0000000..9e82e2e --- /dev/null +++ b/srcs/phpmyadmin/templates/table/gis_visualization/gis_visualization.twig @@ -0,0 +1,80 @@ +<div id="div_view_options"> + <fieldset> + <legend>{% trans 'Display GIS Visualization' %}</legend> + <div id="gis_div" style="position:relative;"> + <form method="post" action="tbl_gis_visualization.php"> + {{ get_hidden_inputs(url_params) }} + <label for="labelColumn"> + {% trans "Label column" %} + </label> + <select name="visualizationSettings[labelColumn]" id="labelColumn" class="autosubmit"> + <option value="">{% trans "-- None --" %}</option> + {% for value in label_candidates %} + <option value="{{ value }}"{{ value == visualization_settings['labelColumn'] ? ' selected="selected"' }}> + {{ value }} + </option> + {% endfor %} + </select> + <label for="spatialColumn"> + {% trans "Spatial column" %} + </label> + <select name="visualizationSettings[spatialColumn]" id="spatialColumn" class="autosubmit"> + {% for value in spatial_candidates %} + <option value="{{ value }}"{{ value == visualization_settings['spatialColumn'] ? ' selected="selected"' }}> + {{ value }} + </option> + {% endfor %} + </select> + <input type="hidden" name="displayVisualization" value="redraw"> + <tr> + <td class="choice" colspan="2"> + <input type="checkbox" + name="visualizationSettings[choice]" + id="choice" value="useBaseLayer" + {% if visualization_settings['choice'] is defined %} + checked="checked" + {% endif %}> + <label for="choice" id="labelChoice"> + {% trans "Use OpenStreetMaps as Base Layer" %} + </label> + </td> + </tr> + {{ get_start_and_number_of_rows_panel(sql_query) }} + </form> + + <div class="pma_quick_warp" style="width: 50px; position: absolute; right: 0; top: 0; cursor: pointer;"> + <div class="drop_list"> + <span class="drop_button" style="padding: 0; border: 0;"> + {{ get_image('b_saveimage', 'Save'|trans) }} + </span> + <ul> + <li class="warp_link"> + <a href="{{ download_url|raw }}&fileFormat=png" class="disableAjax">PNG</a> + </li> + <li class="warp_link"> + <a href="{{ download_url|raw }}&fileFormat=pdf" class="disableAjax">PDF</a> + </li> + <li class="warp_link"> + <a href="{{ download_url|raw }}&fileFormat=svg" class="disableAjax">SVG</a> + </li> + </ul> + </div> + </div> + </div> + + <div class="clearfloat"></div> + + <div id="placeholder" + style="width:{{ visualization_settings['width'] }}px;height:{{ visualization_settings['height'] }}px;"> + {{ visualization|raw }} + </div> + <div id="openlayersmap"></div> + <input type="hidden" id="pmaThemeImage" value="{{ pma_theme_image }}"> + <script language="javascript" type="text/javascript"> + function drawOpenLayers() + { + {{ draw_ol|raw }} + } + </script> + </fieldset> +</div> diff --git a/srcs/phpmyadmin/templates/table/index_form.twig b/srcs/phpmyadmin/templates/table/index_form.twig new file mode 100644 index 0000000..6364599 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/index_form.twig @@ -0,0 +1,223 @@ +<form action="tbl_indexes.php" + method="post" + name="index_frm" + id="index_frm" + class="ajax"> + + {{ get_hidden_inputs(form_params) }} + + <fieldset id="index_edit_fields"> + <div class="index_info"> + <div> + <div class="label"> + <strong> + <label for="input_index_name"> + {% trans 'Index name:' %} + {{ show_hint('"PRIMARY" <b>must</b> be the name of and <b>only of</b> a primary key!'|trans) }} + </label> + </strong> + </div> + + <input type="text" + name="index[Key_name]" + id="input_index_name" + size="25" + maxlength="64" + value="{{ index.getName() }}" + onfocus="this.select()"> + </div> + + <div> + <div class="label"> + <strong> + <label for="select_index_choice"> + {% trans 'Index choice:' %} + {{ show_mysql_docu('ALTER_TABLE') }} + </label> + </strong> + </div> + {{ index.generateIndexChoiceSelector(create_edit_table)|raw }} + </div> + + {% include 'div_for_slider_effect.twig' with { + 'id': 'indexoptions', + 'message': 'Advanced Options'|trans, + 'initial_sliders_state': default_sliders_state + } only %} + + <div> + <div class="label"> + <strong> + <label for="input_key_block_size"> + {% trans 'Key block size:' %} + </label> + </strong> + </div> + + <input type="text" + name="index[Key_block_size]" + id="input_key_block_size" + size="30" + value="{{ index.getKeyBlockSize() }}"> + </div> + + <div> + + <div class="label"> + <strong> + <label for="select_index_type"> + {% trans 'Index type:' %} + {{ show_mysql_docu('ALTER_TABLE') }} + </label> + </strong> + </div> + {{ index.generateIndexTypeSelector()|raw }} + </div> + + <div> + <div class="label"> + <strong> + <label for="input_parser"> + {% trans 'Parser:' %} + </label> + </strong> + </div> + + <input type="text" + name="index[Parser]" + id="input_parse" + size="30" + value="{{ index.getParser() }}"> + </div> + + <div> + <div class="label"> + <strong> + <label for="input_index_comment"> + {% trans 'Comment:' %} + </label> + </strong> + </div> + + <input type="text" + name="index[Index_comment]" + id="input_index_comment" + size="30" + maxlength="1024" + value="{{ index.getComment() }}"> + </div> + </div> + <!-- end of indexoptions div --> + + <div class="clearfloat"></div> + + <table id="index_columns"> + <thead> + <tr> + <th></th> + <th> + {% trans 'Column' %} + </th> + <th> + {% trans 'Size' %} + </th> + </tr> + </thead> + {% set spatial_types = [ + 'geometry', + 'point', + 'linestring', + 'polygon', + 'multipoint', + 'multilinestring', + 'multipolygon', + 'geomtrycollection' + ] %} + <tbody> + {% for column in index.getColumns() %} + <tr class="noclick"> + <td> + <span class="drag_icon" title="{% trans 'Drag to reorder' %}"></span> + </td> + <td> + <select name="index[columns][names][]"> + <option value=""> + -- {% trans 'Ignore' %} -- + </option> + {% for field_name, field_type in fields %} + {% if (index.getChoice() != 'FULLTEXT' + or field_type matches '/(char|text)/i') + and (index.getChoice() != 'SPATIAL' + or field_type in spatial_types) %} + + <option value="{{ field_name }}" + {%- if field_name == column.getName() %} + selected="selected" + {%- endif %}> + {{ field_name }} [{{ field_type }}] + </option> + {% endif %} + {% endfor %} + </select> + </td> + <td> + <input type="text" + size="5" + onfocus="this.select()" + name="index[columns][sub_parts][]" + value="{{ index.getChoice() != 'SPATIAL' ? + column.getSubPart() }}"> + </td> + </tr> + {% endfor %} + {% if add_fields > 0 %} + {% for i in range(1, add_fields) %} + <tr class="noclick"> + <td> + <span class="drag_icon" title="{% trans 'Drag to reorder' %}"></span> + </td> + <td> + <select name="index[columns][names][]"> + <option value="">-- {% trans 'Ignore' %} --</option> + {% set j = 0 %} + {% for field_name, field_type in fields %} + {% if create_edit_table %} + {% set col_index = field_type[1] %} + {% set field_type = field_type[0] %} + {% endif %} + {% set j = j + 1 %} + <option value="{{ col_index is defined ? + col_index : field_name }}" + {{- j == i ? ' selected="selected"' }}> + {{ field_name }} [{{ field_type }}] + </option> + {% endfor %} + </select> + </td> + <td> + <input type="text" + size="5" + onfocus="this.select()" + name="index[columns][sub_parts][]" + value=""> + </td> + </tr> + {% endfor %} + {% endif %} + </tbody> + </table> + <div class="add_more"> + + <div class="slider"></div> + <div class="add_fields hide"> + <input class="btn btn-secondary" type="submit" + id="add_fields" + value="{{ 'Add %s column(s) to index'|trans|format(1) }}"> + </div> + </div> + </fieldset> + <fieldset class="tblFooters"> + <button class="btn btn-secondary" type="submit" id="preview_index_frm">{% trans 'Preview SQL' %}</button> + <input class="btn btn-primary" type="submit" id="save_index_frm" value="{% trans 'Go' %}"> + </fieldset> +</form> diff --git a/srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig b/srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig new file mode 100644 index 0000000..86a8215 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/insert/continue_insertion_form.twig @@ -0,0 +1,19 @@ +<form id="continueForm" method="post" action="tbl_replace.php" name="continueForm"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="goto" value="{{ goto }}"> + <input type="hidden" name="err_url" value="{{ err_url }}"> + <input type="hidden" name="sql_query" value="{{ sql_query }}"> + + {% if has_where_clause %} + {% for key_id, where_clause in where_clause_array %} + <input type="hidden" name="where_clause[{{ key_id }}]" value=" + {{- where_clause|trim }}"> + {% endfor %} + {% endif %} + + {% set insert_rows %} + <input type="number" name="insert_rows" id="insert_rows" value=" + {{- insert_rows_default }}" min="1"> + {% endset %} + {{ 'Continue insertion with %s rows'|trans|format(insert_rows)|raw }} +</form> diff --git a/srcs/phpmyadmin/templates/table/operations/view.twig b/srcs/phpmyadmin/templates/table/operations/view.twig new file mode 100644 index 0000000..e590532 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/operations/view.twig @@ -0,0 +1,31 @@ +<!-- VIEW operations --> +<div> + <form method="post" action="view_operations.php"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="reload" value="1"> + <fieldset> + <legend>{% trans 'Operations' %}</legend> + <table> + <!-- Change view name --> + <tr> + <td>{% trans 'Rename view to' %}</td> + <td><input type="text" name="new_name" onfocus="this.select()" + value="{{ table }}" + required> + </td> + </tr> + </table> + </fieldset> + <fieldset class="tblFooters"> + <input type="hidden" name="submitoptions" value="1"> + <input class="btn btn-primary" type="submit" value="{% trans 'Go' %}"> + </fieldset> + </form> +</div> + +<div> + <fieldset class="caution"> + <legend>{% trans 'Delete data or table' %}</legend> + <ul>{{ delete_data_or_table_link | raw }}</ul> + </fieldset> +</div> diff --git a/srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig b/srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig new file mode 100644 index 0000000..2aae85a --- /dev/null +++ b/srcs/phpmyadmin/templates/table/page_with_secondary_tabs.twig @@ -0,0 +1,22 @@ +{% if cfg_relation['relwork'] or is_foreign_key_supported %} + <ul id="topmenu2"> + {{ get_html_tab({ + 'icon': 'b_props', + 'link': 'tbl_structure.php', + 'text': 'Table structure'|trans, + 'id': 'table_strucuture_id' + }, url_params) }} + {{ get_html_tab({ + 'icon': 'b_relations', + 'link': 'tbl_relation.php', + 'text': 'Relation view'|trans, + 'id': 'table_relation_id' + }, url_params) }} + </ul> + <div class="clearfloat"></div> +{% endif %} + +<div id="structure_content"> + {% block content %} + {% endblock %} +</div> diff --git a/srcs/phpmyadmin/templates/table/relation/common_form.twig b/srcs/phpmyadmin/templates/table/relation/common_form.twig new file mode 100644 index 0000000..e85c6ce --- /dev/null +++ b/srcs/phpmyadmin/templates/table/relation/common_form.twig @@ -0,0 +1,223 @@ +{% extends 'table/page_with_secondary_tabs.twig' %} + +{% block content %} +<form method="post" action="tbl_relation.php"> + {{ get_hidden_inputs(db, table) }} + {# InnoDB #} + {% if is_foreign_key_supported(tbl_storage_engine) %} + <fieldset> + <legend>{% trans 'Foreign key constraints' %}</legend> + <div class="responsivetable jsresponsive"> + <table id="foreign_keys" class="relationalTable"> + <thead><tr> + <th>{% trans 'Actions' %}</th> + <th>{% trans 'Constraint properties' %}</th> + {% if tbl_storage_engine|upper == 'INNODB' %} + <th> + {% trans 'Column' %} + {{ show_hint('Creating a foreign key over a non-indexed column would automatically create an index on it. Alternatively, you can define an index below, before creating the foreign key.'|trans) }} + </th> + {% else %} + <th> + {% trans 'Column' %} + {{ show_hint('Only columns with index will be displayed. You can define an index below.'|trans) }} + </th> + {% endif %} + <th colspan="3"> + {% trans 'Foreign key constraint' %} + ({{ tbl_storage_engine }}) + </th> + </tr> + <tr> + <th></th> + <th></th> + <th></th> + <th>{% trans 'Database' %}</th> + <th>{% trans 'Table' %}</th> + <th>{% trans 'Column' %}</th> + </tr></thead> + {% set i = 0 %} + {% if existrel_foreign is not empty %} + {% for key, one_key in existrel_foreign %} + {# Foreign database dropdown #} + {% set foreign_db = one_key['ref_db_name'] is defined + and one_key['ref_db_name'] is not null + ? one_key['ref_db_name'] : db %} + {% set foreign_table = false %} + {% if foreign_db %} + {% set foreign_table = one_key['ref_table_name'] is defined + and one_key['ref_table_name'] is not null + ? one_key['ref_table_name'] : false %} + {% endif %} + {% set unique_columns = [] %} + {% if foreign_db and foreign_table %} + {% set table_obj = table_get(foreign_table, foreign_db) %} + {% set unique_columns = table_obj.getUniqueColumns(false, false) %} + {% endif %} + {% include 'table/relation/foreign_key_row.twig' with { + 'i': i, + 'one_key': one_key, + 'column_array': column_array, + 'options_array': options_array, + 'tbl_storage_engine': tbl_storage_engine, + 'db': db, + 'table': table, + 'url_params': url_params, + 'databases': databases, + 'foreign_db': foreign_db, + 'foreign_table': foreign_table, + 'unique_columns': unique_columns + } only %} + {% set i = i + 1 %} + {% endfor %} + {% endif %} + {% include 'table/relation/foreign_key_row.twig' with { + 'i': i, + 'one_key': [], + 'column_array': column_array, + 'options_array': options_array, + 'tbl_storage_engine': tbl_storage_engine, + 'db': db, + 'table': table, + 'url_params': url_params, + 'databases': databases, + 'foreign_db': foreign_db, + 'foreign_table': foreign_table, + 'unique_columns': unique_columns + } only %} + {% set i = i + 1 %} + <tr> + <th colspan="6"> + <a class="formelement clearfloat add_foreign_key" href=""> + {% trans '+ Add constraint' %} + </a> + </th> + </tr> + </table> + </div> + </fieldset> + {% endif %} + + {% if cfg_relation['relwork'] %} + {% if is_foreign_key_supported(tbl_storage_engine) %} + {% include 'div_for_slider_effect.twig' with { + 'id': 'ir_div', + 'message': 'Internal relationships'|trans, + 'initial_sliders_state': default_sliders_state + } only %} + {% endif %} + + <fieldset> + <legend> + {% trans 'Internal relationships' %} + {{ show_docu('config', 'cfg_Servers_relation') }} + </legend> + <table id="internal_relations" class="relationalTable"> + <tr> + <th>{% trans 'Column' %}</th> + <th>{% trans 'Internal relation' %} + {% if is_foreign_key_supported(tbl_storage_engine) %} + {{ show_hint('An internal relation is not necessary when a corresponding FOREIGN KEY relation exists.'|trans) }} + {% endif %} + </th> + {% set saved_row_cnt = save_row|length - 1 %} + {% for i in 0..saved_row_cnt %} + {% set myfield = save_row[i]['Field'] %} + {# Use an md5 as array index to avoid having special characters + in the name attribute (see bug #1746964 ) #} + {% set myfield_md5 = column_hash_array[myfield] %} + + {% set foreign_table = false %} + {% set foreign_column = false %} + + {# Database dropdown #} + {% if existrel[myfield] is defined %} + {% set foreign_db = existrel[myfield]['foreign_db'] %} + {% else %} + {% set foreign_db = db %} + {% endif %} + + {# Table dropdown #} + {% set tables = [] %} + {% if foreign_db %} + {% if existrel[myfield] is defined %} + {% set foreign_table = existrel[myfield]['foreign_table'] %} + {% endif %} + {% set tables = dbi.getTables(foreign_db) %} + {% endif %} + + {# Column dropdown #} + {% set unique_columns = [] %} + {% if foreign_db and foreign_table %} + {% if existrel[myfield] is defined %} + {% set foreign_column = existrel[myfield]['foreign_field'] %} + {% endif %} + {% set table_obj = table_get(foreign_table, foreign_db) %} + {% set unique_columns = table_obj.getUniqueColumns(false, false) %} + {% endif %} + + <tr> + <td class="vmiddle"> + <strong>{{ myfield }}</strong> + <input type="hidden" name="fields_name[{{ myfield_md5 }}]" + value="{{ myfield }}"> + </td> + + <td> + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_db[' ~ myfield_md5 ~ ']', + 'title': 'Database'|trans, + 'values': databases, + 'foreign': foreign_db + } only %} + + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_table[' ~ myfield_md5 ~ ']', + 'title': 'Table'|trans, + 'values': tables, + 'foreign': foreign_table + } only %} + + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_column[' ~ myfield_md5 ~ ']', + 'title': 'Column'|trans, + 'values': unique_columns, + 'foreign': foreign_column + } only %} + </td> + </tr> + {% endfor %} + </table> + </fieldset> + {% if is_foreign_key_supported(tbl_storage_engine) %} + </div> + {% endif %} + {% endif %} + + {% if cfg_relation['displaywork'] %} + {% set disp = get_display_field(db, table) %} + <fieldset> + <label>{% trans 'Choose column to display:' %}</label> + <select name="display_field"> + <option value="">---</option> + {% for row in save_row %} + <option value="{{ row['Field'] }}" + {%- if disp is defined and row['Field'] == disp %} + selected="selected" + {%- endif %}> + {{ row['Field'] }} + </option> + {% endfor %} + </select> + </fieldset> + {% endif %} + + <fieldset class="tblFooters"> + <input class="btn btn-secondary preview_sql" type="button" value="{% trans 'Preview SQL' %}"> + <input class="btn btn-primary" type="submit" value="{% trans 'Save' %}"> + </fieldset> +</form> +{% if foreignKeySupported %} + {{ displayIndexesHtml|raw }} +{% endif %} +{% endblock %} diff --git a/srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig b/srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig new file mode 100644 index 0000000..ff179bc --- /dev/null +++ b/srcs/phpmyadmin/templates/table/relation/dropdown_generate.twig @@ -0,0 +1,9 @@ +{{ dropdown_question is not empty ? dropdown_question -}} +<select name="{{ select_name }}"> +{% for one_value, one_label in choices %} + <option value="{{ one_value }}" + {%- if selected_value == one_value %} selected="selected"{% endif %}> + {{ one_label }} + </option> +{% endfor %} +</select> diff --git a/srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig b/srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig new file mode 100644 index 0000000..3df6c34 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/relation/foreign_key_row.twig @@ -0,0 +1,136 @@ +<tr> + {# Drop key anchor #} + <td> + {% set js_msg = '' %} + {% set this_params = null %} + {% if one_key['constraint'] is defined %} + {% set drop_fk_query = 'ALTER TABLE ' ~ backquote(db) ~ '.' ~ backquote(table) + ~ ' DROP FOREIGN KEY ' + ~ backquote(one_key['constraint']) ~ ';' + %} + {% set this_params = url_params %} + {% set this_params = { + 'goto': 'tbl_relation.php', + 'back': 'tbl_relation.php', + 'sql_query': drop_fk_query, + 'message_to_show': 'Foreign key constraint %s has been dropped'|trans|format( + one_key['constraint'] + ) + } %} + {% set js_msg = 'ALTER TABLE ' ~ db ~ '.' ~ table ~ ' DROP FOREIGN KEY ' ~ one_key['constraint'] ~ ';'|js_format %} + {% endif %} + {% if one_key['constraint'] is defined %} + <input type="hidden" class="drop_foreign_key_msg" value=" + {{- js_msg }}"> + {% set drop_url = 'sql.php' ~ get_common(this_params) %} + {% set drop_str = get_icon('b_drop', 'Drop'|trans) %} + {{ link_or_button(drop_url, drop_str, {'class': 'drop_foreign_key_anchor ajax'}) }} + {% endif %} + </td> + <td> + <span class="formelement clearfloat"> + <input type="text" name="constraint_name[{{ i }}]" value=" + {{- one_key['constraint'] is defined ? one_key['constraint'] -}} + " placeholder="{% trans 'Constraint name' %}" maxlength="64"> + </span> + <div class="floatleft"> + {# For ON DELETE and ON UPDATE, the default action + is RESTRICT as per MySQL doc; however, a SHOW CREATE TABLE + won't display the clause if it's set as RESTRICT. #} + {% set on_delete = one_key['on_delete'] is defined + ? one_key['on_delete'] : 'RESTRICT' %} + {% set on_update = one_key['on_update'] is defined + ? one_key['on_update'] : 'RESTRICT' %} + <span class="formelement"> + {% include 'table/relation/dropdown_generate.twig' with { + 'dropdown_question': 'ON DELETE', + 'select_name': 'on_delete[' ~ i ~ ']', + 'choices': options_array, + 'selected_value': on_delete + } only %} + </span> + <span class="formelement"> + {% include 'table/relation/dropdown_generate.twig' with { + 'dropdown_question': 'ON UPDATE', + 'select_name': 'on_update[' ~ i ~ ']', + 'choices': options_array, + 'selected_value': on_update + } only %} + </span> + </div> + </td> + <td> + {% if one_key['index_list'] is defined %} + {% for key, column in one_key['index_list'] %} + <span class="formelement clearfloat"> + {% include 'table/relation/dropdown_generate.twig' with { + 'dropdown_question': '', + 'select_name': 'foreign_key_fields_name[' ~ i ~ '][]', + 'choices': column_array, + 'selected_value': column + } only %} + </span> + {% endfor %} + {% else %} + <span class="formelement clearfloat"> + {% include 'table/relation/dropdown_generate.twig' with { + 'dropdown_question': '', + 'select_name': 'foreign_key_fields_name[' ~ i ~ '][]', + 'choices': column_array, + 'selected_value': '' + } only %} + </span> + {% endif %} + <a class="formelement clearfloat add_foreign_key_field" data-index=" + {{- i }}" href=""> + {% trans '+ Add column' %} + </a> + </td> + {% set tables = [] %} + {% if foreign_db %} + {% set tables = get_tables(foreign_db, tbl_storage_engine) %} + {% endif %} + <td> + <span class="formelement clearfloat"> + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_foreign_db[' ~ i ~ ']', + 'title': 'Database'|trans, + 'values': databases, + 'foreign': foreign_db + } only %} + </span> + </td> + <td> + <span class="formelement clearfloat"> + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_foreign_table[' ~ i ~ ']', + 'title': 'Table'|trans, + 'values': tables, + 'foreign': foreign_table + } only %} + </span> + </td> + <td> + {% if foreign_db and foreign_table %} + {% for foreign_column in one_key['ref_index_list'] %} + <span class="formelement clearfloat"> + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_foreign_column[' ~ i ~ '][]', + 'title': 'Column'|trans, + 'values': unique_columns, + 'foreign': foreign_column + } only %} + </span> + {% endfor %} + {% else %} + <span class="formelement clearfloat"> + {% include 'table/relation/relational_dropdown.twig' with { + 'name': 'destination_foreign_column[' ~ i ~ '][]', + 'title': 'Column'|trans, + 'values': [], + 'foreign': '' + } only %} + </span> + {% endif %} + </td> +</tr> diff --git a/srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig b/srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig new file mode 100644 index 0000000..9d5f3c9 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/relation/relational_dropdown.twig @@ -0,0 +1,18 @@ +<select name="{{ name }}" title="{{ title }}"> + <option value=""></option> + {% set seen_key = false %} + {% for value in values %} + <option value="{{ value }}" + {%- if foreign is not same as(false) and value == foreign %} + selected="selected" + {%- set seen_key = true -%} + {%- endif %}> + {{ value }} + </option> + {% endfor %} + {% if foreign is not same as(false) and not seen_key %} + <option value="{{ foreign }}" selected="selected"> + {{ foreign }} + </option> + {% endif %} +</select> diff --git a/srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig b/srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig new file mode 100644 index 0000000..b72e530 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/column_comparison_operators.twig @@ -0,0 +1,3 @@ +<select id="ColumnOperator{{ search_index }}" name="criteriaColumnOperators[{{ search_index }}]"> + {{ type_operators|raw }} +</select> diff --git a/srcs/phpmyadmin/templates/table/search/fields_table.twig b/srcs/phpmyadmin/templates/table/search/fields_table.twig new file mode 100644 index 0000000..8b74939 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/fields_table.twig @@ -0,0 +1,33 @@ +<table class="data"{{ search_type == 'zoom' ? ' id="tableFieldsId"' }}> + <thead> + <tr> + {% if geom_column_flag %} + <th>{% trans 'Function' %}</th> + {% endif %} + <th>{% trans 'Column' %}</th> + <th>{% trans 'Type' %}</th> + <th>{% trans 'Collation' %}</th> + <th>{% trans 'Operator' %}</th> + <th>{% trans 'Value' %}</th> + </tr> + </thead> + <tbody> + {% if search_type == 'zoom' %} + {% include 'table/search/rows_zoom.twig' with { + 'self': self, + 'column_names': column_names, + 'keys': keys, + 'criteria_column_names': criteria_column_names, + 'criteria_column_types': criteria_column_types + } only %} + {% else %} + {% include 'table/search/rows_normal.twig' with { + 'self': self, + 'geom_column_flag': geom_column_flag, + 'column_names': column_names, + 'column_types': column_types, + 'column_collations': column_collations + } only %} + {% endif %} + </tbody> +</table> diff --git a/srcs/phpmyadmin/templates/table/search/form_tag.twig b/srcs/phpmyadmin/templates/table/search/form_tag.twig new file mode 100644 index 0000000..1017abd --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/form_tag.twig @@ -0,0 +1,4 @@ +<form method="post" action="{{ script_name }}" name="insertForm" id="{{ form_id }}" class="ajax lock-page"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="goto" value="{{ goto }}"> + <input type="hidden" name="back" value="{{ script_name }}"> diff --git a/srcs/phpmyadmin/templates/table/search/geom_func.twig b/srcs/phpmyadmin/templates/table/search/geom_func.twig new file mode 100644 index 0000000..f7a7415 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/geom_func.twig @@ -0,0 +1,19 @@ +{# Displays 'Function' column if it is present #} +<td> + {% set geom_types = get_gis_datatypes() %} + {% if column_types[column_index] in geom_types %} + <select class="geom_func" name="geom_func[{{ column_index }}]"> + {# get the relevant list of GIS functions #} + {% set funcs = get_gis_functions(column_types[column_index], true, true) %} + + {% for func_name, func in funcs %} + {% set name = func['display'] is defined ? func['display'] : func_name %} + <option value="{{ name }}"> + {{ name }} + </option> + {% endfor %} + </select> + {% else %} + + {% endif %} +</td> diff --git a/srcs/phpmyadmin/templates/table/search/input_box.twig b/srcs/phpmyadmin/templates/table/search/input_box.twig new file mode 100644 index 0000000..5c30535 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/input_box.twig @@ -0,0 +1,97 @@ +{# Get inputbox based on different column types (Foreign key, geometrical, enum) #} +{% if foreigners and search_column_in_foreigners(foreigners, column_name) %} + {% if foreign_data['disp_row'] is iterable %} + <select name="criteriaValues[{{ column_index }}]" + id="{{ column_id }}{{ column_index }}"> + {{ foreign_dropdown( + foreign_data['disp_row'], + foreign_data['foreign_field'], + foreign_data['foreign_display'], + '', + foreign_max_limit + ) }} + </select> + {% elseif foreign_data['foreign_link'] == true %} + <input type="text" + id="{{ column_id }}{{ column_index }}" + name="criteriaValues[{{ column_index }}]" + id="field_{{ column_name_hash }}[{{ column_index }}]" + class="textfield" + {% if criteria_values[column_index] is defined %} + value="{{ criteria_values[column_index] }}" + {% endif %}> + <a class="ajax browse_foreign" href="browse_foreigners.php" data-post=" + {{- get_common({'db': db, 'table': table}, '') -}} + &field={{ column_name|url_encode }}&fieldkey= + {{- column_index }}&fromsearch=1"> + {{ titles['Browse']|replace({"'": "\\'"})|raw }} + </a> + {% endif %} +{% elseif column_type in get_gis_datatypes() %} + <input type="text" + name="criteriaValues[{{ column_index }}]" + size="40" + class="textfield" + id="field_{{ column_index }}"> + {% if in_fbs %} + {% set edit_url = 'gis_data_editor.php' ~ get_common() %} + {% set edit_str = get_icon('b_edit', 'Edit/Insert'|trans) %} + <span class="open_search_gis_editor"> + {{ link_or_button(edit_url, edit_str, [], '_blank') }} + </span> + {% endif %} +{% elseif column_type starts with 'enum' + or (column_type starts with 'set' and in_zoom_search_edit) %} + {% set in_zoom_search_edit = false %} + {% set value = column_type|e|slice(5, -1)|replace({''': ''})|split(', ') %} + {% set cnt_value = value|length %} + {# + Enum in edit mode --> dropdown + Enum in search mode --> multiselect + Set in edit mode --> multiselect + Set in search mode --> input (skipped here, so the 'else' section would handle it) + #} + {% if (column_type starts with 'enum' and not in_zoom_search_edit) + or (column_type starts with 'set' and in_zoom_search_edit) %} + <select name="criteriaValues[{{ column_index }}]" + id="{{ column_id }}{{ column_index }}"> + {% else %} + <select name="criteriaValues[{{ column_index }}]" + id="{{ column_id }}{{ column_index }}" + multiple="multiple" + size="{{ min(3, cnt_value) }}"> + {% endif %} + {# Add select options #} + <option value=""></option> + {% for i in 0..cnt_value - 1 %} + {% if criteria_values[column_index] is defined + and criteria_values[column_index] is iterable + and value[i] in criteria_values[column_index] %} + <option value="{{ value[i]|raw }}" selected> + {{ value[i]|raw }} + </option> + {% else %} + <option value="{{ value[i]|raw }}"> + {{ value[i]|raw }} + </option> + {% endif %} + {% endfor %} + </select> +{% else %} + {% set the_class = 'textfield' %} + {% if column_type == 'date' %} + {% set the_class = the_class ~ ' datefield' %} + {% elseif column_type == 'datetime' or column_type starts with 'timestamp' %} + {% set the_class = the_class ~ ' datetimefield' %} + {% elseif column_type starts with 'bit' %} + {% set the_class = the_class ~ ' bit' %} + {% endif %} + <input type="text" + name="criteriaValues[{{ column_index }}]" + size="40" + class="{{ the_class }}" + id="{{ column_id }}{{ column_index }}" + {% if criteria_values[column_index] is defined %} + value="{{ criteria_values[column_index] }}" + {%- endif %}> +{% endif %} diff --git a/srcs/phpmyadmin/templates/table/search/replace_preview.twig b/srcs/phpmyadmin/templates/table/search/replace_preview.twig new file mode 100644 index 0000000..e7a2423 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/replace_preview.twig @@ -0,0 +1,39 @@ +<form method="post" + action="tbl_find_replace.php" + name="previewForm" + id="previewForm"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="replace" value="true"> + <input type="hidden" name="columnIndex" value="{{ column_index }}"> + <input type="hidden" name="findString" value="{{ find }}"> + <input type="hidden" name="replaceWith" value="{{ replace_with }}"> + <input type="hidden" name="useRegex" value="{{ use_regex }}"> + + <fieldset id="fieldset_find_replace_preview"> + <legend>{% trans 'Find and replace - preview' %}</legend> + <table id="previewTable"> + <thead> + <tr> + <th>{% trans 'Count' %}</th> + <th>{% trans 'Original string' %}</th> + <th>{% trans 'Replaced string' %}</th> + </tr> + </thead> + <tbody> + {% if result is iterable %} + {% for row in result %} + <tr> + <td class="right">{{ row[2] }}</td>{# count #} + <td>{{ row[0] }}</td>{# original #} + <td>{{ row[1] }}</td>{# replaced #} + </tr> + {% endfor %} + {% endif %} + </tbody> + </table> + </fieldset> + + <fieldset class="tblFooters"> + <input class="btn btn-secondary" type="submit" name="replace" value="{% trans 'Replace' %}"> + </fieldset> +</form> diff --git a/srcs/phpmyadmin/templates/table/search/rows_normal.twig b/srcs/phpmyadmin/templates/table/search/rows_normal.twig new file mode 100644 index 0000000..5e21efa --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/rows_normal.twig @@ -0,0 +1,39 @@ +{% for column_index in 0..column_names|length - 1 %} + <tr class="noclick"> + {# If 'Function' column is present trying to change comment #} + {% if geom_column_flag %} + {% include 'table/search/geom_func.twig' with { + 'column_index': column_index, + 'column_types': column_types + } only %} + {% endif %} + {# Displays column's name, type, collation and value #} + <th> + {{ column_names[column_index] }} + </th> + {% set properties = self.getColumnProperties(column_index, column_index) %} + <td dir="ltr"> + {{ properties['type'] }} + </td> + <td> + {{ properties['collation'] }} + </td> + <td> + {{ properties['func']|raw }} + </td> + {# here, the data-type attribute is needed for a date/time picker #} + <td data-type="{{ properties['type'] }}"> + {{ properties['value']|raw }} + {# Displays hidden fields #} + <input type="hidden" + name="criteriaColumnNames[{{ column_index }}]" + value="{{ column_names[column_index] }}"> + <input type="hidden" + name="criteriaColumnTypes[{{ column_index }}]" + value="{{ column_types[column_index] }}"> + <input type="hidden" + name="criteriaColumnCollations[{{ column_index }}]" + value="{{ column_collations[column_index] }}"> + </td> + </tr> +{% endfor %} diff --git a/srcs/phpmyadmin/templates/table/search/rows_zoom.twig b/srcs/phpmyadmin/templates/table/search/rows_zoom.twig new file mode 100644 index 0000000..dc46f1d --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/rows_zoom.twig @@ -0,0 +1,74 @@ +{# Get already set search criteria (if any) #} +{% set type = [] %} +{% set collation = [] %} +{% set func = [] %} +{% set value = [] %} + +{% for i in 0..3 %} + {# After X-Axis and Y-Axis column rows, display additional criteria option #} + {% if i == 2 %} + <tr> + <td> + {% trans 'Additional search criteria' %} + </td> + </tr> + {% endif %} + <tr class="noclick"> + <th> + <select name="criteriaColumnNames[]" id="tableid_{{ i }}" > + <option value="pma_null"> + {% trans 'None' %} + </option> + {% for j in 0..column_names|length - 1 %} + {% if criteria_column_names[i] is defined + and criteria_column_names[i] == column_names[j] %} + <option value="{{ column_names[j] }}" selected="selected"> + {{ column_names[j] }} + </option> + {% else %} + <option value="{{ column_names[j] }}"> + {{ column_names[j] }} + </option> + {% endif %} + {% endfor %} + </select> + </th> + {% if criteria_column_names[i] is defined + and criteria_column_names[i] != 'pma_null' %} + {% set key = keys[criteria_column_names[i]] %} + {% set properties = self.getColumnProperties(i, key) %} + {% set type = type|merge({i: properties['type']}) %} + {% set collation = collation|merge({i: properties['collation']}) %} + {% set func = func|merge({i: properties['func']}) %} + {% set value = value|merge({i: properties['value']}) %} + {% endif %} + {# Column type #} + <td dir="ltr"> + {{ type[i] is defined ? type[i] }} + </td> + {# Column Collation #} + <td> + {{ collation[i] is defined ? collation[i] }} + </td> + {# Select options for column operators #} + <td> + {{ func[i] is defined ? func[i]|raw }} + </td> + {# Inputbox for search criteria value #} + <td> + </td> + <td> + {{ value[i] is defined ? value[i]|raw }} + {# Displays hidden fields #} + <input type="hidden" + name="criteriaColumnTypes[{{ i }}]" + id="types_{{ i }}" + {%- if criteria_column_types[i] is defined %} + value="{{ criteria_column_types[i] }}" + {%- endif %}> + <input type="hidden" + name="criteriaColumnCollations[{{ i }}]" + id="collations_{{ i }}"> + </td> + </tr> +{% endfor %} diff --git a/srcs/phpmyadmin/templates/table/search/selection_form.twig b/srcs/phpmyadmin/templates/table/search/selection_form.twig new file mode 100644 index 0000000..2ba4d60 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/selection_form.twig @@ -0,0 +1,226 @@ +{% if search_type == 'zoom' %} + {% include 'table/search/form_tag.twig' with { + 'script_name': 'tbl_zoom_select.php', + 'form_id': 'zoom_search_form', + 'db': db, + 'table': table, + 'goto': goto + } only %} + <fieldset id="fieldset_zoom_search"> + <fieldset id="inputSection"> + <legend> + {% trans 'Do a "query by example" (wildcard: "%") for two different columns' %} + </legend> + {% include 'table/search/fields_table.twig' with { + 'self': self, + 'search_type': search_type, + 'geom_column_flag': geom_column_flag, + 'column_names': column_names, + 'column_types': column_types, + 'column_collations': column_collations, + 'keys' : keys, + 'criteria_column_names': criteria_column_names, + 'criteria_column_types': criteria_column_types + } only %}<table class="data"> + {# Select options for data label #} + <tr> + <td> + <label for="dataLabel"> + {% trans 'Use this column to label each point' %} + </label> + </td> + <td> + <select name="dataLabel" id="dataLabel" > + <option value = ""> + {% trans 'None' %} + </option> + {% for i in 0..column_names|length - 1 %} + {% if data_label is defined and data_label == column_names[i]|e %} + <option value="{{ column_names[i] }}" selected="selected"> + {{ column_names[i] }} + </option> + {% else %} + <option value="{{ column_names[i] }}" > + {{ column_names[i] }} + </option> + {% endif %} + {% endfor %} + </select> + </td> + </tr> + {# Inputbox for changing default maximum rows to plot #} + <tr> + <td> + <label for="maxRowPlotLimit"> + {% trans 'Maximum rows to plot' %} + </label> + </td> + <td> + <input type="number" + name="maxPlotLimit" + id="maxRowPlotLimit" + required="required" + value="{{ max_plot_limit }}"> + </td> + </tr> + </table> + </fieldset> + </fieldset> +{% elseif search_type == 'normal' %} + {% include 'table/search/form_tag.twig' with { + 'script_name': 'tbl_select.php', + 'form_id': 'tbl_search_form', + 'db': db, + 'table': table, + 'goto': goto + } only %} + <fieldset id="fieldset_table_search"> + <fieldset id="fieldset_table_qbe"> + <legend> + {% trans 'Do a "query by example" (wildcard: "%")' %} + </legend> + <div class="responsivetable jsresponsive"> + {% include 'table/search/fields_table.twig' with { + 'self': self, + 'search_type': search_type, + 'geom_column_flag': geom_column_flag, + 'column_names': column_names, + 'column_types': column_types, + 'column_collations': column_collations, + 'criteria_column_names': criteria_column_names, + 'criteria_column_types': criteria_column_types + } only %} + </div> + <div id="gis_editor"></div> + <div id="popup_background"></div> + </fieldset> + {% include 'div_for_slider_effect.twig' with { + 'id': 'searchoptions', + 'message': 'Options'|trans, + 'initial_sliders_state': default_sliders_state + } only %} + + {# Displays columns select list for selecting distinct columns in the search #} + <fieldset id="fieldset_select_fields"> + <legend> + {% trans 'Select columns (at least one):' %} + </legend> + <select name="columnsToDisplay[]" + size="{{ min(column_names|length, 10) }}" + multiple="multiple"> + {% for each_field in column_names %} + <option value="{{ each_field }}" + selected="selected"> + {{ each_field }} + </option> + {% endfor %} + </select> + <input type="checkbox" name="distinct" value="DISTINCT" id="oDistinct"> + <label for="oDistinct">DISTINCT</label> + </fieldset> + + {# Displays input box for custom 'Where' clause to be used in the search #} + <fieldset id="fieldset_search_conditions"> + <legend> + <em>{% trans 'Or' %}</em> + {% trans 'Add search conditions (body of the "where" clause):' %} + </legend> + {{ show_mysql_docu('Functions') }} + <input type="text" name="customWhereClause" class="textfield" size="64"> + </fieldset> + + {# Displays option of changing default number of rows displayed per page #} + <fieldset id="fieldset_limit_rows"> + <legend>{% trans 'Number of rows per page' %}</legend> + <input type="number" + name="session_max_rows" + required="required" + min="1" + value="{{ max_rows }}" + class="textfield"> + </fieldset> + + {# Displays option for ordering search results by a column value (Asc or Desc) #} + <fieldset id="fieldset_display_order"> + <legend>{% trans 'Display order:' %}</legend> + <select name="orderByColumn"><option value="--nil--"></option> + {% for each_field in column_names %} + <option value="{{ each_field }}"> + {{ each_field }} + </option> + {% endfor %} + </select> + + {{ get_radio_fields( + 'order', + { + 'ASC': 'Ascending'|trans, + 'DESC': 'Descending'|trans + }, + 'ASC', + false, + true, + 'formelement' + ) }} + + </fieldset> + <div class="clearfloat"></div> + </fieldset> +{% elseif search_type == 'replace' %} + {% include 'table/search/form_tag.twig' with { + 'script_name': 'tbl_find_replace.php', + 'form_id': 'find_replace_form', + 'db': db, + 'table': table, + 'goto': goto + } only %} + <fieldset id="fieldset_find_replace"> + <fieldset id="fieldset_find"> + <legend> + {% trans 'Find and replace' %} + </legend>{% trans 'Find:' %} + <input type="text" value="" name="find" required> + {% trans 'Replace with:' %} + <input type="text" value="" name="replaceWith"> + + {% trans 'Column:' %} + <select name="columnIndex"> + {% for i in 0..column_names|length - 1 %} + {% set type = types[column_names[i]] %} + + {% if sql_types.getTypeClass(type) == 'CHAR' %} + <option value="{{ i }}"> + {{- column_names[i] -}} + </option> + {% endif %} + {% endfor %} + </select> + + {% include 'checkbox.twig' with { + 'html_field_id': 'useRegex', + 'html_field_name': 'useRegex', + 'label': 'Use regular expression'|trans, + 'checked': false, + 'onclick': false + } only %} + </fieldset> + </fieldset> +{% else %} + {% include 'table/search/form_tag.twig' with { + 'script_name': '', + 'form_id': '', + 'db': db, + 'table': table, + 'goto': goto + } only %} +{% endif %} + +{# Displays selection form's footer elements #} + <fieldset class="tblFooters"> + <input class="btn btn-primary" type="submit" + name="{{ search_type == 'zoom' ? 'zoom_submit' : 'submit' }}" + {{ search_type == 'zoom' ? 'id="inputFormSubmitId"' }} + value="{% trans 'Go' %}"> + </fieldset> +</form> +<div id="sqlqueryresultsouter"></div> diff --git a/srcs/phpmyadmin/templates/table/search/zoom_result_form.twig b/srcs/phpmyadmin/templates/table/search/zoom_result_form.twig new file mode 100644 index 0000000..7543f85 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/search/zoom_result_form.twig @@ -0,0 +1,86 @@ +<form method="post" action="tbl_zoom_select.php" name="displayResultForm" id="zoom_display_form" class="ajax"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="goto" value="{{ goto }}"> + <input type="hidden" name="back" value="tbl_zoom_select.php"> + + <fieldset id="displaySection"> + <legend>{% trans 'Browse/Edit the points' %}</legend> + + {# JSON encode the data(query result) #} + <center> + {% if zoom_submit and data is not empty %} + <div id="resizer"> + <center> + <a id="help_dialog" href="#"> + {% trans 'How to use' %} + </a> + </center> + <div id="querydata" class="hide"> + {{ data_json }} + </div> + <div id="querychart"></div> + <button class="button-reset"> + {% trans 'Reset zoom' %} + </button> + </div> + {% endif %} + </center> + + {# Displays rows in point edit form #} + <div id="dataDisplay" class="hide"> + <table> + <thead> + <tr> + <th>{% trans 'Column' %}</th> + <th>{% trans 'Null' %}</th> + <th>{% trans 'Value' %}</th> + </tr> + </thead> + <tbody> + {% for column_index in 0..column_names|length - 1 %} + {% set field_popup = column_names[column_index] %} + {% set foreign_data = get_foreign_data( + foreigners, + field_popup, + false, + '', + '' + ) %} + <tr class="noclick"> + <th>{{ column_names[column_index] }}</th> + {# Null checkbox if column can be null #} + <th> + {% if column_null_flags[column_index] == 'YES' %} + <input type="checkbox" class="checkbox_null" + name="criteriaColumnNullFlags[{{ column_index }}]" + id="edit_fields_null_id_{{ column_index }}"> + {% endif %} + </th> + {# Column's Input box #} + <th> + {% include 'table/search/input_box.twig' with { + 'str': '', + 'column_type': column_types[column_index], + 'column_id': column_types[column_index] ? 'edit_fieldID_' : 'fieldID_', + 'in_zoom_search_edit': true, + 'foreigners': foreigners, + 'column_name': field_popup, + 'column_name_hash': column_name_hashes[field_popup], + 'foreign_data': foreign_data, + 'table': table, + 'column_index': column_index, + 'foreign_max_limit': foreign_max_limit, + 'criteria_values': '', + 'db': db, + 'titles': titles, + 'in_fbs': false + } only %} + </th> + </tr> + {% endfor %} + </tbody> + </table> + </div> + <input type="hidden" id="queryID" name="sql_query"> + </fieldset> +</form> diff --git a/srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig b/srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig new file mode 100644 index 0000000..d9c629c --- /dev/null +++ b/srcs/phpmyadmin/templates/table/structure/action_row_in_structure_table.twig @@ -0,0 +1,31 @@ +<li class="{{ class }}"> +{% if type == 'text' + or type == 'blob' + or tbl_storage_engine == 'ARCHIVE' + or has_field %} + {{ titles['No' ~ action]|raw }} +{% else %} + <a rel="samepage" class="ajax add_key print_ignore + {%- if has_link_class %} + add_primary_key_anchor + {%- elseif action == 'Index' %} + add_index_anchor + {%- elseif action == 'Unique' %} + add_unique_anchor + {%- elseif action == 'Spatial' %} + add_spatial_anchor + {%- endif %}" href="tbl_structure.php" data-post="{{ url_query|raw -}} + &add_key=1&sql_query= + {{- ('ALTER TABLE ' ~ + backquote(table) ~ + (is_primary ? (primary ? ' DROP PRIMARY KEY,')) ~ + ' ' ~ + syntax ~ + '(' ~ + backquote(row['Field']) ~ + ');')|url_encode -}} + &message_to_show={{ message|format(row['Field']|e)|url_encode }}"> + {{ titles[action]|raw }} + </a> +{% endif %} +</li> diff --git a/srcs/phpmyadmin/templates/table/structure/display_partitions.twig b/srcs/phpmyadmin/templates/table/structure/display_partitions.twig new file mode 100644 index 0000000..b10a0bc --- /dev/null +++ b/srcs/phpmyadmin/templates/table/structure/display_partitions.twig @@ -0,0 +1,145 @@ +<div id="partitions"> + <fieldset> + <legend> + {% trans 'Partitions' %} + {{ show_mysql_docu('partitioning') }} + </legend> + {% if partitions is empty %} + {{ 'No partitioning defined!'|trans|notice }} + {% else %} + <p> + {% trans 'Partitioned by:' %} + <code>{{ partition_method }}({{ partition_expression }})</code> + </p> + {% if has_sub_partitions %} + <p> + {% trans 'Sub partitioned by:' %} + <code>{{ sub_partition_method }}({{ sub_partition_expression }})</code> + <p> + {% endif %} + <table> + <thead> + <tr> + <th colspan="2">#</th> + <th>{% trans 'Partition' %}</th> + {% if has_description %} + <th>{% trans 'Expression' %}</th> + {% endif %} + <th>{% trans 'Rows' %}</th> + <th>{% trans 'Data length' %}</th> + <th>{% trans 'Index length' %}</th> + <th>{% trans 'Comment' %}</th> + <th colspan="{{ range_or_list ? '7' : '6' }}"> + {% trans 'Action' %} + </th> + </tr> + </thead> + <tbody> + {% for partition in partitions %} + <tr class="noclick{{ has_sub_partitions ? ' marked' }}"> + {% if has_sub_partitions %} + <td>{{ partition.getOrdinal() }}</td> + <td></td> + {% else %} + <td colspan="2">{{ partition.getOrdinal() }}</td> + {% endif %} + <th>{{ partition.getName() }}</th> + {% if has_description %} + <td> + <code> + {{- partition.getExpression() -}} + {{- partition.getMethod() == 'LIST' ? ' IN (' : ' < ' -}} + {{- partition.getDescription() -}} + {{- partition.getMethod() == 'LIST' ? ')' -}} + </code> + </td> + {% endif %} + <td class="value">{{ partition.getRows() }}</td> + <td class="value"> + {% set data_length = format_byte_down( + partition.getDataLength(), + 3, + 1 + ) %} + <span>{{ data_length[0] }}</span> + <span class="unit">{{ data_length[1] }}</span> + </td> + <td class="value"> + {% set index_length = format_byte_down( + partition.getIndexLength(), + 3, + 1 + ) %} + <span>{{ index_length[0] }}</span> + <span class="unit">{{ index_length[1] }}</span> + </td> + <td>{{ partition.getComment() }}</td> + {% for action, icon in action_icons %} + <td> + <a href="tbl_structure.php" data-post="{{ url_query -}} + &partition_maintenance=1&sql_query= + {{- ("ALTER TABLE " ~ backquote(table) ~ " " ~ action + ~ " PARTITION " ~ partition.getName())|url_encode }}" + id="partition_action_{{ action }}" + name="partition_action_{{ action }}" + class="ajax"> + {{ icon|raw }} + </a> + </td> + {% endfor %} + + {% if has_sub_partitions %} + {% for sub_partition in partition.getSubPartitions() %} + <tr class="noclick"> + <td></td> + <td>{{ sub_partition.getOrdinal() }}</td> + <td>{{ sub_partition.getName() }}</td> + {% if has_description %} + <td></td> + {% endif %} + <td class="value">{{ sub_partition.getRows() }}</td> + <td class="value"> + {% set data_length = format_byte_down( + sub_partition.getDataLength(), + 3, + 1 + ) %} + <span>{{ data_length[0] }}</span> + <span class="unit">{{ data_length[1] }}</span> + </td> + <td class="value"> + {% set index_length = format_byte_down( + sub_partition.getIndexLength(), + 3, + 1 + ) %} + <span>{{ index_length[0] }}</span> + <span class="unit">{{ index_length[1] }}</span> + </td> + <td>{{ sub_partition.getComment() }}</td> + <td colspan="{{ range_or_list ? '7' : '6' }}"></td> + </tr> + {% endfor %} + {% endif %} + </tr> + {% endfor %} + </tbody> + </table> + {% endif %} + </fieldset> + <fieldset class="tblFooters print_ignore"> + <form action="tbl_structure.php" method="post"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="edit_partitioning" value="true"> + {% if partitions is empty %} + <input class="btn btn-secondary" type="submit" name="edit_partitioning" value="{% trans 'Partition table' %}"> + {% else %} + {{ link_or_button(remove_url, 'Remove partitioning'|trans, { + 'class': 'button ajax', + 'id': 'remove_partitioning' + }) }} + <input class="btn btn-secondary" type="submit" name="edit_partitioning" value="{% trans 'Edit partitioning' %}"> + {% endif %} + </form> + </fieldset> +</div> diff --git a/srcs/phpmyadmin/templates/table/structure/display_structure.twig b/srcs/phpmyadmin/templates/table/structure/display_structure.twig new file mode 100644 index 0000000..16e11db --- /dev/null +++ b/srcs/phpmyadmin/templates/table/structure/display_structure.twig @@ -0,0 +1,516 @@ +{% extends 'table/page_with_secondary_tabs.twig' %} +{% block content %} +<form method="post" action="tbl_structure.php" name="fieldsForm" id="fieldsForm" + class="ajax{{ hide_structure_actions ? ' HideStructureActions' }}"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="table_type" value= + {%- if db_is_system_schema -%} + "information_schema" + {%- elseif tbl_is_view -%} + "view" + {%- else -%} + "table" + {%- endif %}> + <div class="responsivetable"> + <table id="tablestructure" class="data topmargin"> + {# Table header #} + <thead> + <tr> + <th class="print_ignore"></th> + <th>#</th> + <th>{% trans 'Name' %}</th> + <th>{% trans 'Type' %}</th> + <th>{% trans 'Collation' %}</th> + <th>{% trans 'Attributes' %}</th> + <th>{% trans 'Null' %}</th> + <th>{% trans 'Default' %}</th> + {% if show_column_comments -%} + <th>{% trans 'Comments' %}</th> + {%- endif %} + <th>{% trans 'Extra' %}</th> + {# @see table/structure.js, function moreOptsMenuResize() #} + {% if not db_is_system_schema and not tbl_is_view %} + <th colspan="{{ show_icons('ActionLinksMode') ? '8' : '9' -}} + " class="action print_ignore">{% trans 'Action' %}</th> + {% endif %} + </tr> + </thead> + <tbody> + {# Table body #} + {% set rownum = 0 %} + {% for row in fields %} + {% set rownum = rownum + 1 %} + + {% set extracted_columnspec = extracted_columnspecs[rownum] %} + {% set field_name = row['Field']|e %} + {# For column comments #} + {% set comments = row_comments[rownum] %} + {# Underline commented fields and display a hover-title (CSS only) #} + + <tr> + <td class="center print_ignore"> + <input type="checkbox" class="checkall" name="selected_fld[]" value="{{ row['Field'] }}" id="checkbox_row_{{ rownum }}"> + </td> + <td class="right">{{ rownum }}</td> + <th class="nowrap"> + <label for="checkbox_row_{{ rownum }}"> + {% if displayed_fields[rownum].comment is defined %} + <span class="commented_column" title="{{ displayed_fields[rownum].comment }}">{{ displayed_fields[rownum].text }}</span> + {% else %} + {{ displayed_fields[rownum].text }} + {% endif %} + {{ displayed_fields[rownum].icon|raw }} + </label> + </th> + <td{{ 'set' != extracted_columnspec['type'] and 'enum' != extracted_columnspec['type'] ? ' class="nowrap"' }}> + <bdo dir="ltr" lang="en"> + {{ extracted_columnspec['displayed_type']|raw }} + {% if relation_commwork and relation_mimework and browse_mime + and mime_map[row['Field']]['mimetype'] is defined %} + <br>{% trans 'Media (MIME) type:' %} {{ mime_map[row['Field']]['mimetype']|replace({'_': '/'})|lower }} + {% endif %} + </bdo> + </td> + <td> + {% if row['Collation'] is not empty %} + <dfn title="{{ collations[row['Collation']].description }}">{{ collations[row['Collation']].name }}</dfn> + {% endif %} + </td> + <td class="column_attribute nowrap">{{ attributes[rownum] }}</td> + <td>{{ row['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td> + <td class="nowrap"> + {% if row['Default'] is not null %} + {% if extracted_columnspec['type'] == 'bit' %} + {{ row['Default']|convert_bit_default_value }} + {% else %} + {{ row['Default'] }} + {% endif %} + {% elseif row['Null'] == 'YES' %} + <em>NULL</em> + {% else %} + <em>{% trans %}None{% context %}None for default{% endtrans %}</em> + {% endif %} + </td> + {% if show_column_comments %} + <td> + {{ comments }} + </td> + {% endif %} + <td class="nowrap">{{ row['Extra']|upper }}</td> + {% if not tbl_is_view and not db_is_system_schema %} + <td class="edit center print_ignore"> + <a class="change_column_anchor ajax" href="tbl_structure.php + {{- url_query }}&field={{ row['Field']|url_encode }}&change_column=1"> + {{ titles['Change']|raw }} + </a> + </td> + <td class="drop center print_ignore"> + <a class="drop_column_anchor ajax" href="sql.php" data-post="{{ url_query }}&sql_query= + {{- ('ALTER TABLE ' ~ backquote(table) + ~ ' DROP ' ~ backquote(row['Field']) ~ ';')|url_encode -}} + &dropped_column={{ row['Field']|url_encode }}&purge=1&message_to_show= + {{- ('Column %s has been dropped.'|trans|format(row['Field']|e))|url_encode }}"> + {{ titles['Drop']|raw }} + </a> + </td> + {% endif %} + + {% if not tbl_is_view and not db_is_system_schema %} + {% set type = extracted_columnspec['print_type'] is not empty ? extracted_columnspec['print_type'] %} + <td class="print_ignore"> + <ul class="table-structure-actions resizable-menu"> + {% if hide_structure_actions %} + <li class="submenu shown"> + <a href="#" class="tab nowrap">{{ get_icon('b_more', 'More'|trans) }}</a> + <ul> + {% endif %} + {# Add primary #} + {% include 'table/structure/action_row_in_structure_table.twig' with { + 'type': type, + 'tbl_storage_engine': tbl_storage_engine, + 'class': 'primary nowrap', + 'has_field': primary and primary.hasColumn(field_name), + 'has_link_class': true, + 'url_query': url_query, + 'primary': primary, + 'syntax': 'ADD PRIMARY KEY', + 'message': 'A primary key has been added on %s.'|trans, + 'action': 'Primary', + 'titles': titles, + 'row': row, + 'is_primary': true, + 'table': table + } only %} + + {# Add unique #} + {% include 'table/structure/action_row_in_structure_table.twig' with { + 'type': type, + 'tbl_storage_engine': tbl_storage_engine, + 'class': 'add_unique unique nowrap', + 'has_field': field_name in columns_with_unique_index, + 'has_link_class': false, + 'url_query': url_query, + 'primary': primary, + 'syntax': 'ADD UNIQUE', + 'message': 'An index has been added on %s.'|trans, + 'action': 'Unique', + 'titles': titles, + 'row': row, + 'is_primary': false, + 'table': table + } only %} + + {# Add index #} + {% include 'table/structure/action_row_in_structure_table.twig' with { + 'type': type, + 'tbl_storage_engine': tbl_storage_engine, + 'class': 'add_index nowrap', + 'has_field': false, + 'has_link_class': false, + 'url_query': url_query, + 'primary': primary, + 'syntax': 'ADD INDEX', + 'message': 'An index has been added on %s.'|trans, + 'action': 'Index', + 'titles': titles, + 'row': row, + 'is_primary': false, + 'table': table + } only %} + + {# Add spatial #} + {% set spatial_types = [ + 'geometry', + 'point', + 'linestring', + 'polygon', + 'multipoint', + 'multilinestring', + 'multipolygon', + 'geomtrycollection' + ] %} + {% include 'table/structure/action_row_in_structure_table.twig' with { + 'type': type, + 'tbl_storage_engine': tbl_storage_engine, + 'class': 'spatial nowrap', + 'has_field': type not in spatial_types and + (tbl_storage_engine == 'MYISAM' or mysql_int_version >= 50705), + 'has_link_class': false, + 'url_query': url_query, + 'primary': primary, + 'syntax': 'ADD SPATIAL', + 'message': 'An index has been added on %s.'|trans, + 'action': 'Spatial', + 'titles': titles, + 'row': row, + 'is_primary': false, + 'table': table + } only %} + + {# FULLTEXT is possible on TEXT, CHAR and VARCHAR #} + <li class="fulltext nowrap"> + {% if tbl_storage_engine is not empty and ( + tbl_storage_engine == 'MYISAM' + or tbl_storage_engine == 'ARIA' + or tbl_storage_engine == 'MARIA' + or (tbl_storage_engine == 'INNODB' and mysql_int_version >= 50604) + ) and ('text' in type or 'char' in type) %} + <a rel="samepage" class="ajax add_key add_fulltext_anchor" href="tbl_structure.php" + data-post="{{- url_query|raw }}&add_key=1&sql_query= + {{- ('ALTER TABLE ' ~ backquote(table) + ~ ' ADD FULLTEXT(' ~ backquote(row['Field']) + ~ ');')|url_encode }}&message_to_show= + {{- ('An index has been added on %s.'|trans|format(row['Field']|e))|url_encode }}"> + {{ titles['IdxFulltext']|raw }} + </a> + {% else %} + {{ titles['NoIdxFulltext']|raw }} + {% endif %} + </li> + + {# Distinct value action #} + <li class="browse nowrap"> + <a href="sql.php" data-post="{{ url_query|raw }}&sql_query= + {{- ('SELECT COUNT(*) AS ' ~ backquote('Rows'|trans) + ~ ', ' ~ backquote(row['Field']) + ~ ' FROM ' ~ backquote(table) + ~ ' GROUP BY ' ~ backquote(row['Field']) + ~ ' ORDER BY ' ~ backquote(row['Field']))|url_encode -}} + &is_browse_distinct=1"> + {{ titles['DistinctValues']|raw }} + </a> + </li> + {% if central_columns_work %} + <li class="browse nowrap"> + {% if row['Field'] in central_list %} + <a href="#" class="central_columns remove_button"> + {{ get_icon('centralColumns_delete', 'Remove from central columns'|trans) }} + </a> + {% else %} + <a href="#" class="central_columns add_button"> + {{ get_icon('centralColumns_add', 'Add to central columns'|trans) }} + </a> + {% endif %} + </li> + {% endif %} + {% if hide_structure_actions %} + </ul> + </li> + {% endif %} + </ul> + </td> + {% endif %} + </tr> + {% endfor %} + </tbody> + </table> + </div> + <div class="print_ignore"> + {% include 'select_all.twig' with { + 'pma_theme_image': pma_theme_image, + 'text_dir': text_dir, + 'form_name': 'fieldsForm' + } only %} + + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Browse'|trans, + 'b_browse', + 'browse' + ) }} + + {% if not tbl_is_view and not db_is_system_schema %} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit change_columns_anchor ajax', + 'Change'|trans, + 'b_edit', + 'change' + ) }} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Drop'|trans, + 'b_drop', + 'drop' + ) }} + + {% if tbl_storage_engine != 'ARCHIVE' %} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Primary'|trans, + 'b_primary', + 'primary' + ) }} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Unique'|trans, + 'b_unique', + 'unique' + ) }} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Index'|trans, + 'b_index', + 'index' + ) }} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Fulltext'|trans, + 'b_ftext', + 'ftext' + ) }} + + {% if tbl_storage_engine is not empty and ( + tbl_storage_engine == 'MYISAM' + or tbl_storage_engine == 'ARIA' + or tbl_storage_engine == 'MARIA') %} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Fulltext'|trans, + 'b_ftext', + 'ftext' + ) }} + {% endif %} + + {% if central_columns_work %} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Add to central columns'|trans, + 'centralColumns_add', + 'add_to_central_columns' + ) }} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Remove from central columns'|trans, + 'centralColumns_delete', + 'remove_from_central_columns' + ) }} + {% endif %} + {% endif %} + {% endif %} + </div> +</form> +<hr class="print_ignore"> +<div id="move_columns_dialog" class="hide" title="{% trans 'Move columns' %}"> + <p>{% trans 'Move the columns by dragging them up and down.' %}</p> + <form action="tbl_structure.php" name="move_column_form" id="move_column_form"> + <div> + {{ get_hidden_inputs(db, table) }} + <ul></ul> + </div> + </form> +</div> +{# Work on the table #} +<div id="structure-action-links"> + {% if tbl_is_view and not db_is_system_schema %} + {% set edit_view_url = 'view_create.php' ~ edit_view_url %} + {{ link_or_button( + edit_view_url, + get_icon('b_edit', 'Edit view'|trans, true) + ) }} + {% endif %} + <a href="#" id="printView">{{ get_icon('b_print', 'Print'|trans, true) }}</a> + {% if not tbl_is_view and not db_is_system_schema %} + {# Only display propose table structure for MySQL < 8.0 #} + {% if mysql_int_version < 80000 or is_mariadb %} + <a href="sql.php" data-post="{{ url_query|raw }}&session_max_rows=all&sql_query= + {{- ('SELECT * FROM ' ~ backquote(table) ~ ' PROCEDURE ANALYSE()')|url_encode -}} + " style="margin-right: 0;"> + {{ get_icon( + 'b_tblanalyse', + 'Propose table structure'|trans, + true + ) }} + </a> + {{ show_mysql_docu('procedure_analyse') }} + {% endif %} + {% if is_active %} + <a href="tbl_tracking.php{{ url_query|raw }}"> + {{ get_icon('eye', 'Track table'|trans, true) }} + </a> + {% endif %} + <a href="#" id="move_columns_anchor"> + {{ get_icon('b_move', 'Move columns'|trans, true) }} + </a> + <a href="normalization.php{{ url_query|raw }}"> + {{ get_icon('normalize', 'Normalize'|trans, true) }} + </a> + {% endif %} + {% if tbl_is_view and not db_is_system_schema %} + {% if is_active %} + <a href="tbl_tracking.php{{ url_query|raw }}"> + {{ get_icon('eye', 'Track view'|trans, true) }} + </a> + {% endif %} + {% endif %} +</div> +{% if not tbl_is_view and not db_is_system_schema %} + <form method="post" action="tbl_addfield.php" id="addColumns" name="addColumns"> + {{ get_hidden_inputs(db, table) }} + {% if show_icons('ActionLinksMode') %} + {{ get_image('b_insrow', 'Add column'|trans) }} + {% endif %} + {% set num_fields -%} + <input type="number" name="num_fields" value="1" onfocus="this.select()" min="1" required> + {%- endset %} + {{ 'Add %s column(s)'|trans|format(num_fields)|raw }} + <input type="hidden" name="field_where" value="after"> + {# I tried displaying the drop-down inside the label but with Firefox the drop-down was blinking #} + <select name="after_field"> + <option value="first" data-pos="first"> + {% trans 'at beginning of table' %} + </option> + {% for one_column_name in columns_list %} + <option value="{{ one_column_name }}" + {{- loop.revindex0 == 0 ? ' selected="selected"' }}> + {{ 'after %s'|trans|format(one_column_name) }} + </option> + {% endfor %} + </select> + <input class="btn btn-primary" type="submit" value="{% trans 'Go' %}"> + </form> +{% endif %} + +{# Displays indexes #} +{% if not tbl_is_view and not db_is_system_schema + and 'ARCHIVE' != tbl_storage_engine %} + {{ displayIndexesHtml|raw }} +{% endif %} + +{# Display partition details #} +{% if have_partitioning %} + {# Detect partitioning #} + {% if partition_names is not empty and partition_names[0] is not null %} + {% set first_partition = partitions[0] %} + {% set range_or_list = first_partition.getMethod() == 'RANGE' + or first_partition.getMethod() == 'RANGE COLUMNS' + or first_partition.getMethod() == 'LIST' + or first_partition.getMethod() == 'LIST COLUMNS' %} + {% set sub_partitions = first_partition.getSubPartitions() %} + {% set has_sub_partitions = first_partition.hasSubPartitions() %} + {% if has_sub_partitions %} + {% set first_sub_partition = sub_partitions[0] %} + {% endif %} + + {% set action_icons = { + 'ANALYZE': get_icon('b_search', 'Analyze'|trans), + 'CHECK': get_icon('eye', 'Check'|trans), + 'OPTIMIZE': get_icon('normalize', 'Optimize'|trans), + 'REBUILD': get_icon('s_tbl', 'Rebuild'|trans), + 'REPAIR': get_icon('b_tblops', 'Repair'|trans), + 'TRUNCATE': get_icon('b_empty', 'Truncate'|trans), + } %} + {% if range_or_list %} + {% set action_icons = action_icons|merge({'DROP': get_icon('b_drop', 'Drop'|trans)}) %} + {% endif %} + + {# open Slider Effect div #} + {% include 'div_for_slider_effect.twig' with { + 'id': 'partitions-2', + 'message': 'Partitions'|trans, + 'initial_sliders_state': default_sliders_state + } only %} + + {% set remove_sql = 'ALTER TABLE ' ~ backquote(table) ~ ' REMOVE PARTITIONING' %} + {% set remove_url = 'sql.php' ~ url_query ~ '&sql_query=' ~ remove_sql|url_encode %} + + {% include 'table/structure/display_partitions.twig' with { + 'db': db, + 'table': table, + 'url_query': url_query, + 'partitions': partitions, + 'partition_method': first_partition.getMethod(), + 'partition_expression': first_partition.getExpression(), + 'has_description': first_partition.getDescription() is not empty, + 'has_sub_partitions': has_sub_partitions, + 'sub_partition_method': has_sub_partitions ? first_sub_partition.getMethod(), + 'sub_partition_expression': has_sub_partitions ? first_sub_partition.getExpression(), + 'action_icons': action_icons, + 'range_or_list': range_or_list, + 'remove_url': remove_url + } only %} + {% else %} + {% include 'table/structure/display_partitions.twig' with { + 'db': db, + 'table': table + } only %} + {% endif %} + {# For closing Slider effect div #} + </div> +{% endif %} + +{# Displays Space usage and row statistics #} +{% if show_stats %} + {{ table_stats|raw }} +{% endif %} +<div class="clearfloat"></div> +{% endblock %} diff --git a/srcs/phpmyadmin/templates/table/structure/display_table_stats.twig b/srcs/phpmyadmin/templates/table/structure/display_table_stats.twig new file mode 100644 index 0000000..01c74ae --- /dev/null +++ b/srcs/phpmyadmin/templates/table/structure/display_table_stats.twig @@ -0,0 +1,169 @@ +<div id="tablestatistics"> + <fieldset> + <legend>{% trans 'Information' %}</legend> + {% if showtable['TABLE_COMMENT'] %} + <p> + <strong>{% trans 'Table comments:' %}</strong> + {{ showtable['TABLE_COMMENT'] }} + </p> + {% endif %} + <a id="showusage"></a> + + {% if not tbl_is_view and not db_is_system_schema %} + <table id="tablespaceusage" class="width100 data"> + <caption class="tblHeaders">{% trans 'Space usage' %}</caption> + <tbody> + <tr> + <th class="name">{% trans 'Data' %}</th> + <td class="value">{{ data_size }}</td> + <td class="unit">{{ data_unit }}</td> + </tr> + + {% if index_size is defined %} + <tr> + <th class="name">{% trans 'Index' %}</th> + <td class="value">{{ index_size }}</td> + <td class="unit">{{ index_unit }}</td> + </tr> + {% endif %} + + {% if free_size is defined %} + <tr> + <th class="name">{% trans 'Overhead' %}</th> + <td class="value">{{ free_size }}</td> + <td class="unit">{{ free_unit }}</td> + </tr> + <tr> + <th class="name">{% trans 'Effective' %}</th> + <td class="value">{{ effect_size }}</td> + <td class="unit">{{ effect_unit }}</td> + </tr> + {% endif %} + + {% if tot_size is defined and mergetable == false %} + <tr> + <th class="name">{% trans 'Total' %}</th> + <td class="value">{{ tot_size }}</td> + <td class="unit">{{ tot_unit }}</td> + </tr> + {% endif %} + + {# Optimize link if overhead #} + {% if free_size is defined + and (tbl_storage_engine == 'MYISAM' + or tbl_storage_engine == 'ARIA' + or tbl_storage_engine == 'MARIA' + or tbl_storage_engine == 'BDB') + or (tbl_storage_engine == 'INNODB' and innodb_file_per_table == true) %} + <tr class="tblFooters print_ignore"> + <td colspan="3" class="center"> + <a href="sql.php" data-post="{{ url_query }}&pos=0&sql_query= + {{- ('OPTIMIZE TABLE ' ~ backquote(table))|url_encode }}"> + {{ get_icon('b_tbloptimize', 'Optimize table'|trans) }} + </a> + </td> + </tr> + {% endif %} + </tbody> + </table> + {% endif %} + + {% set avg_size = avg_size is defined ? avg_size : null %} + {% set avg_unit = avg_unit is defined ? avg_unit : null %} + <table id="tablerowstats" class="width100 data"> + <caption class="tblHeaders">{% trans 'Row statistics' %}</caption> + <tbody> + {% if showtable['Row_format'] is defined %} + <tr> + <th class="name">{% trans 'Format' %}</th> + {% if showtable['Row_format'] == 'Fixed' %} + <td class="value">{% trans 'static' %}</td> + {% elseif showtable['Row_format'] == 'Dynamic' %} + <td class="value">{% trans 'dynamic' %}</td> + {% else %} + <td class="value">{{ showtable['Row_format'] }}</td> + {% endif %} + </tr> + {% endif %} + + {% if showtable['Create_options'] is not empty %} + <tr> + <th class="name">{% trans 'Options' %}</th> + {% if showtable['Create_options'] == 'partitioned' %} + <td class="value">{% trans 'partitioned' %}</td> + {% else %} + <td class="value">{{ showtable['Create_options'] }}</td> + {% endif %} + </tr> + {% endif %} + + {% if table_collation is not empty %} + <tr> + <th class="name">{% trans 'Collation' %}</th> + <td class="value"> + <dfn title="{{ table_collation.description }}"> + {{ table_collation.name }} + </dfn> + </td> + </tr> + {% endif %} + + {% if not is_innodb and showtable['Rows'] is defined %} + <tr> + <th class="name">{% trans 'Rows' %}</th> + <td class="value">{{ format_number(showtable['Rows'], 0) }}</td> + </tr> + {% endif %} + + {% if not is_innodb + and showtable['Avg_row_length'] is defined + and showtable['Avg_row_length'] > 0 %} + <tr> + <th class="name">{% trans 'Row length' %}</th> + {% set avg_row_length = format_byte_down(showtable['Avg_row_length'], 6, 1) %} + <td class="value">{{ avg_row_length[0] }} {{ avg_row_length[1] }}</td> + </tr> + {% endif %} + + {% if not is_innodb + and showtable['Data_length'] is defined + and showtable['Rows'] is defined + and showtable['Rows'] > 0 + and mergetable == false %} + <tr> + <th class="name">{% trans 'Row size' %}</th> + <td class="value">{{ avg_size }} {{ avg_unit }}</td> + </tr> + {% endif %} + + {% if showtable['Auto_increment'] is defined %} + <tr> + <th class="name">{% trans 'Next autoindex' %}</th> + <td class="value">{{ format_number(showtable['Auto_increment'], 0) }}</td> + </tr> + {% endif %} + + {% if showtable['Create_time'] is defined %} + <tr> + <th class="name">{% trans 'Creation' %}</th> + <td class="value">{{ localised_date(showtable['Create_time']|date('U')) }}</td> + </tr> + {% endif %} + + {% if showtable['Update_time'] is defined %} + <tr> + <th class="name">{% trans 'Last update' %}</th> + <td class="value">{{ localised_date(showtable['Update_time']|date('U')) }}</td> + </tr> + {% endif %} + + {% if showtable['Check_time'] is defined %} + <tr> + <th class="name">{% trans 'Last check' %}</th> + <td class="value">{{ localised_date(showtable['Check_time']|date('U')) }}</td> + </tr> + {% endif %} + </tbody> + </table> + </fieldset> +</div> diff --git a/srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig b/srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig new file mode 100644 index 0000000..7cf5e8d --- /dev/null +++ b/srcs/phpmyadmin/templates/table/structure/partition_definition_form.twig @@ -0,0 +1,14 @@ +<form action="tbl_structure.php" method="post"> + {{ get_hidden_inputs(db, table) }} + <input type="hidden" name="edit_partitioning" value="true"> + + <fieldset> + <legend>{% trans 'Edit partitioning' %}</legend> + {% include 'columns_definitions/partitions.twig' with { + 'partition_details': partition_details + } only %} + </fieldset> + <fieldset class="tblFooters"> + <input class="btn btn-primary" type="submit" name="save_partitioning" value="{% trans 'Save' %}"> + </fieldset> +</form> diff --git a/srcs/phpmyadmin/templates/table/tracking/main.twig b/srcs/phpmyadmin/templates/table/tracking/main.twig new file mode 100644 index 0000000..ff6c5c4 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/tracking/main.twig @@ -0,0 +1,132 @@ +{% if selectable_tables_num_rows > 0 %} + <form method="post" action="tbl_tracking.php{{ url_query|raw }}"> + {{ get_hidden_inputs(db, table) }} + <select name="table" class="autosubmit"> + {% for entry in selectable_tables_entries %} + <option value="{{ entry.table_name }}" + {{- entry.table_name == selected_table ? ' selected' }}> + {{ entry.db_name }}.{{ entry.table_name }} + {% if entry.is_tracked %} + ({% trans 'active' %}) + {% else %} + ({% trans 'not active' %}) + {% endif %} + </option> + {% endfor %} + </select> + <input type="hidden" name="show_versions_submit" value="1"> + </form> +{% endif %} +<br> +{% if last_version > 0 %} + <form method="post" action="tbl_tracking.php" name="versionsForm" id="versionsForm" class="ajax"> + {{ get_hidden_inputs(db, table) }} + <table id="versions" class="data"> + <thead> + <tr> + <th></th> + <th>{% trans 'Version' %}</th> + <th>{% trans 'Created' %}</th> + <th>{% trans 'Updated' %}</th> + <th>{% trans 'Status' %}</th> + <th>{% trans 'Action' %}</th> + <th>{% trans 'Show' %}</th> + </tr> + </thead> + <tbody> + {% for version in versions %} + <tr> + <td class="center"> + <input type="checkbox" name="selected_versions[]" + class="checkall" id="selected_versions_{{- version['version']|escape }}" + value="{{- version['version']|escape }}"> + </td> + <td class="floatright"> + <label for="selected_versions_{{- version['version']|escape }}"> + <b>{{ version['version']|escape }}</b> + </label> + </td> + <td>{{ version['date_created']|escape }}</td> + <td>{{ version['date_updated']|escape }}</td> + {% if version['tracking_active'] == 1 %} + {% set last_version_status = 1 %} + <td>{% trans 'active' %}</td> + {% else %} + {% set last_version_status = 0 %} + <td>{% trans 'not active' %}</td> + {% endif %} + <td> + <a class="delete_version_anchor ajax" href="tbl_tracking.php" data-post=" + {{- get_common(url_params|merge({ + 'version': version['version'], + 'submit_delete_version': true + }), '') }}"> + {{ get_icon('b_drop', 'Delete version'|trans) }} + </a> + </td> + <td> + <a href="tbl_tracking.php" data-post=" + {{- get_common(url_params|merge({ + 'version': version['version'], + 'report': 'true' + }), '') }}"> + {{ get_icon('b_report', 'Tracking report'|trans) }} + </a> + <a href="tbl_tracking.php" data-post=" + {{- get_common(url_params|merge({ + 'version': version['version'], + 'snapshot': 'true' + }), '') }}"> + {{ get_icon('b_props', 'Structure snapshot'|trans) }} + </a> + </td> + </tr> + {% endfor %} + </tbody> + </table> + {% include 'select_all.twig' with { + 'pma_theme_image': pmaThemeImage, + 'text_dir': text_dir, + 'form_name': 'versionsForm', + } only %} + {{ get_button_or_image( + 'submit_mult', + 'mult_submit', + 'Delete version'|trans, + 'b_drop', + 'delete_version' + ) }} + </form> + {% set last_version_element = versions|first %} + <div> + <form method="post" action="tbl_tracking.php{{ url_query|raw }}"> + {{ get_hidden_inputs(db, table) }} + <fieldset> + <legend> + {% if last_version_element['tracking_active'] == 0 %} + {% set legend = 'Activate tracking for %s'|trans %} + {% set value = 'activate_now' %} + {% set button = 'Activate now'|trans %} + {% else %} + {% set legend = 'Deactivate tracking for %s'|trans %} + {% set value = 'deactivate_now' %} + {% set button = 'Deactivate now'|trans %} + {% endif %} + + {{ legend|format(db ~ '.' ~ table) }} + </legend> + <input type="hidden" name="version" value="{{ last_version }}"> + <input type="hidden" name="toggle_activation" value="{{ value }}"> + <input class="btn btn-secondary" type="submit" value="{{ button }}"> + </fieldset> + </form> + </div> +{% endif %} +{% include 'create_tracking_version.twig' with { + 'url_query': url_query, + 'last_version': last_version, + 'db': db, + 'selected': [table], + 'type': type, + 'default_statements': default_statements, +} only %} diff --git a/srcs/phpmyadmin/templates/table/tracking/report_table.twig b/srcs/phpmyadmin/templates/table/tracking/report_table.twig new file mode 100644 index 0000000..fe00526 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/tracking/report_table.twig @@ -0,0 +1,27 @@ +<table id="{{ table_id }}" class="data"> + <thead> + <tr> + <th>{% trans %}#{% context %}Number{% endtrans %}</th> + <th>{% trans 'Date' %}</th> + <th>{% trans 'Username' %}</th> + <th>{{ header_message }}</th> + <th>{% trans 'Action' %}</th> + </tr> + </thead> + <tbody> + {% for entry in entries %} + <tr class="noclick"> + <td class="right"><small>{{ entry.line_number }}</small></td> + <td><small>{{ entry.date }}</small></td> + <td><small>{{ entry.username }}</small></td> + <td>{{ entry.formated_statement|raw }}</td> + <td class="nowrap"> + <a class="delete_entry_anchor ajax" href="tbl_tracking.php" data-post=" + {{- entry.url_params|raw }}"> + {{ drop_image_or_text|raw }} + </a> + </td> + </tr> + {% endfor %} + </tbody> +</table> diff --git a/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig new file mode 100644 index 0000000..4ef8c21 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_columns.twig @@ -0,0 +1,56 @@ +<h3>{% trans 'Structure' %}</h3> +<table id="tablestructure" class="data"> + <thead> + <tr> + <th>{% trans %}#{% context %}Number{% endtrans %}</th> + <th>{% trans 'Column' %}</th> + <th>{% trans 'Type' %}</th> + <th>{% trans 'Collation' %}</th> + <th>{% trans 'Null' %}</th> + <th>{% trans 'Default' %}</th> + <th>{% trans 'Extra' %}</th> + <th>{% trans 'Comment' %}</th> + </tr> + </thead> + <tbody> + {% set index = 1 %} + {% for field in columns %} + <tr class="noclick"> + <td>{{ index }}</td> + {% set index = index + 1 %} + <td> + <strong> + {{ field['Field'] }} + {% if field['Key'] == 'PRI' %} + {{ get_image('b_primary', 'Primary'|trans) }} + {% elseif field['Key'] is not empty %} + {{ get_image('bd_primary', 'Index'|trans) }} + {% endif %} + </strong> + </td> + <td>{{ field['Type'] }}</td> + <td>{{ field['Collation'] }}</td> + <td>{{ field['Null'] == 'YES' ? 'Yes'|trans : 'No'|trans }}</td> + <td> + {% if field['Default'] is defined %} + {% set extracted_columnspec = extract_column_spec(field['Type']) %} + {% if extracted_columnspec['type'] == 'bit' %} + {# here, $field['Default'] contains something like b'010' #} + {{ field['Default']|convert_bit_default_value }} + {% else %} + {{ field['Default'] }} + {% endif %} + {% else %} + {% if field['Null'] == 'YES' %} + <em>NULL</em> + {% else %} + <em>{% trans %}None{% context %}None for default{% endtrans %}</em> + {% endif %} + {% endif %} + </td> + <td>{{ field['Extra'] }}</td> + <td>{{ field['Comment'] }}</td> + </tr> + {% endfor %} + </tbody> +</table> diff --git a/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig new file mode 100644 index 0000000..a919252 --- /dev/null +++ b/srcs/phpmyadmin/templates/table/tracking/structure_snapshot_indexes.twig @@ -0,0 +1,33 @@ +<h3>{% trans 'Indexes' %}</h3> +<table id="tablestructure_indexes" class="data"> + <thead> + <tr> + <th>{% trans 'Keyname' %}</th> + <th>{% trans 'Type' %}</th> + <th>{% trans 'Unique' %}</th> + <th>{% trans 'Packed' %}</th> + <th>{% trans 'Column' %}</th> + <th>{% trans 'Cardinality' %}</th> + <th>{% trans 'Collation' %}</th> + <th>{% trans 'Null' %}</th> + <th>{% trans 'Comment' %}</th> + </tr> + </thead> + <tbody> + {% for index in indexes %} + <tr class="noclick"> + <td> + <strong>{{ index['Key_name'] }}</strong> + </td> + <td>{{ index['Index_type'] }}</td> + <td>{{ index['Non_unique'] == 0 ? 'Yes'|trans : 'No'|trans }}</td> + <td>{{ index['Packed'] != '' ? 'Yes'|trans : 'No'|trans }}</td> + <td>{{ index['Column_name'] }}</td> + <td>{{ index['Cardinality'] }}</td> + <td>{{ index['Collation'] }}</td> + <td>{{ index['Null'] }}</td> + <td>{{ index['Comment'] }}</td> + </tr> + {% endfor %} + </tbody> +</table> |
