Use the full tab space for CodeMirror instances on dialogues where appropriate. Fixes #4540
|
|
@ -9,7 +9,7 @@ a function, the new function is not the same entity as the old; you must drop
|
|||
existing rules, views, triggers, etc. that refer to the old function.
|
||||
|
||||
The *Function* dialog organizes the development of a function through the
|
||||
following dialog tabs: *General*, *Definition*, *Options*, *Arguments*,
|
||||
following dialog tabs: *General*, *Definition*, *Code*, *Options*,
|
||||
*Parameters*, and *Security*. The *SQL* tab displays the SQL code generated by
|
||||
dialog selections.
|
||||
|
||||
|
|
@ -39,6 +39,27 @@ Use the fields in the *Definition* tab to define the function:
|
|||
returned by the function, if any.
|
||||
* Use the drop-down listbox next to *Language* to select the implementation
|
||||
language. The default is *sql*.
|
||||
* Use the fields in the *Arguments* to define an argument. Click the *Add*
|
||||
icon (+) to set parameters and values for the argument:
|
||||
|
||||
* Use the drop-down listbox in the *Data type* field to select a data type.
|
||||
* Use the drop-down listbox in the *Mode* field to select a mode. Select *IN*
|
||||
for an input parameter; select *OUT* for an output parameter; select *INOUT*
|
||||
for both an input and an output parameter; or, select *VARIADIC* to specify a
|
||||
VARIADIC parameter.
|
||||
* Provide a name for the argument in the *Argument Name* field.
|
||||
* Specify a default value for the argument in the *Default Value* field.
|
||||
|
||||
Click the *Add* icon (+) to define another argument; to discard an argument,
|
||||
click the trash icon to the left of the row and confirm deletion in the *Delete
|
||||
Row* popup.
|
||||
|
||||
Click the *Code* tab to continue.
|
||||
|
||||
.. image:: images/function_code.png
|
||||
:alt: Function dialog code tab
|
||||
:align: center
|
||||
|
||||
* Use the *Code* field to write the code that will execute when the function
|
||||
is called.
|
||||
|
||||
|
|
@ -90,27 +111,6 @@ function:
|
|||
* Use the *Support function* field to specify a planner support function to
|
||||
use for the function.
|
||||
|
||||
Click the *Arguments* tab to continue.
|
||||
|
||||
.. image:: images/function_arguments.png
|
||||
:alt: Function dialog arguments tab
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Arguments* tab to define an argument. Click the *Add*
|
||||
icon (+) to set parameters and values for the argument:
|
||||
|
||||
* Use the drop-down listbox in the *Data type* field to select a data type.
|
||||
* Use the drop-down listbox in the *Mode* field to select a mode. Select *IN*
|
||||
for an input parameter; select *OUT* for an output parameter; select *INOUT*
|
||||
for both an input and an output parameter; or, select *VARIADIC* to specify a
|
||||
VARIADIC parameter.
|
||||
* Provide a name for the argument in the *Argument Name* field.
|
||||
* Specify a default value for the argument in the *Default Value* field.
|
||||
|
||||
Click the *Add* icon (+) to define another argument; to discard an argument,
|
||||
click the trash icon to the left of the row and confirm deletion in the *Delete
|
||||
Row* popup.
|
||||
|
||||
Click the *Parameters* tab to continue.
|
||||
|
||||
.. image:: images/function_parameters.png
|
||||
|
|
@ -177,9 +177,8 @@ the *Function* dialog:
|
|||
:alt: Function dialog sql tab
|
||||
:align: center
|
||||
|
||||
The example demonstrates creating an *edbspl* function named *emp_comp*. The
|
||||
function adds two columns (p_sal and p_comm), and then uses the result to
|
||||
compute a yearly salary, returning a NUMERIC value.
|
||||
The example demonstrates creating an *plpgsql* function named *hire_salesmen*. The
|
||||
function have three columns (p_ename, p_sal and p_comm).
|
||||
|
||||
* Click the *Info* button (i) to access online help.
|
||||
* Click the *Save* button to save work.
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 80 KiB |
|
|
@ -7,7 +7,7 @@
|
|||
Use the *Package* dialog to create a (user-defined) package specification.
|
||||
|
||||
The *Package* dialog organizes the management of a package through the following
|
||||
dialog tabs: *General*, *Code*, and *Security*. The *SQL* tab displays the SQL
|
||||
dialog tabs: *General*, *Header*, *Body*, and *Security*. The *SQL* tab displays the SQL
|
||||
code generated by dialog selections.
|
||||
|
||||
.. image:: images/package_general.png
|
||||
|
|
@ -22,17 +22,22 @@ Use the fields in the *General* tab to identify the package:
|
|||
in the *Schema* field.
|
||||
* Store notes about the package in the *Comment* field.
|
||||
|
||||
Click the *Code* tab to continue.
|
||||
Click the *Header* tab to continue.
|
||||
|
||||
.. image:: images/package_code.png
|
||||
:alt: Package dialog code tab
|
||||
.. image:: images/package_header.png
|
||||
:alt: Package dialog header tab
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Code* tab to specify the package contents and to provide
|
||||
implementation details:
|
||||
Use the *Header* field to define the public interface for the package.
|
||||
|
||||
* Use the *Header* field to define the public interface for the package.
|
||||
* Use the *Body* field to provide the code that implements each package object.
|
||||
Click the *Body* tab to continue.
|
||||
|
||||
.. image:: images/package_body.png
|
||||
:alt: Package dialog body tab
|
||||
:align: center
|
||||
|
||||
|
||||
Use the *Body* field to provide the code that implements each package object.
|
||||
|
||||
Click the *Security* tab to continue.
|
||||
|
||||
|
|
@ -63,7 +68,7 @@ modifies a package definition:
|
|||
:align: center
|
||||
|
||||
The example shown demonstrates creating a package named *empinfo* that includes
|
||||
one function and one procedure.
|
||||
two function and two procedure.
|
||||
|
||||
* Click the *Save* button to save work.
|
||||
* Click the *Cancel* button to exit without saving work.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ New features
|
|||
|
||||
| `Issue #4333 <https://redmine.postgresql.org/issues/4333>`_ - Add support for planner support functions in PostgreSQL 12+ functions.
|
||||
| `Issue #4334 <https://redmine.postgresql.org/issues/4334>`_ - Add support for generated columns in Postgres 12+.
|
||||
| `Issue #4540 <https://redmine.postgresql.org/issues/4540>`_ - Use the full tab space for CodeMirror instances on dialogues where appropriate.
|
||||
| `Issue #4549 <https://redmine.postgresql.org/issues/4549>`_ - Allow a banner to be displayed on the login and other related pages showing custom text.
|
||||
|
||||
Housekeeping
|
||||
|
|
|
|||
|
|
@ -91,9 +91,7 @@ the *Trigger* dialog:
|
|||
:alt: Trigger dialog sql tab
|
||||
:align: center
|
||||
|
||||
The example demonstrates creating a trigger named *log_update* that calls a
|
||||
procedure named *log_account_update* that logs any updates to the *distributors*
|
||||
table.
|
||||
The example demonstrates creating a trigger named *log_update*.
|
||||
|
||||
* Click the *Info* button (i) to access online help.
|
||||
* Click the *Save* button to save work.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Use the *Trigger function* dialog to create or manage a trigger_function. A
|
|||
trigger function defines the action that will be invoked when a trigger fires.
|
||||
|
||||
The *Trigger function* dialog organizes the development of a trigger function
|
||||
through the following dialog tabs: *General*, *Definition*, *Options*,
|
||||
through the following dialog tabs: *General*, *Definition*, *Code*, *Options*,
|
||||
*Parameters* and *Security*. The *SQL* tab displays the SQL code generated by
|
||||
dialog selections.
|
||||
|
||||
|
|
@ -43,6 +43,13 @@ Use the fields in the *Definition* tab to define the trigger function:
|
|||
|
||||
* Use the drop-down listbox next to *Language* to select the implementation
|
||||
language. The default is *plpgsql*.
|
||||
|
||||
Click the *Code* tab to continue.
|
||||
|
||||
.. image:: images/trigger_function_code.png
|
||||
:alt: Trigger function dialog code tab
|
||||
:align: center
|
||||
|
||||
* Use the *Code* field to write the code that will execute when the trigger
|
||||
function is called.
|
||||
|
||||
|
|
@ -158,9 +165,7 @@ the *Trigger function* dialog:
|
|||
:alt: Trigger function dialog sql tab
|
||||
:align: center
|
||||
|
||||
The example shown demonstrates creating a trigger function named *emp_stamp*
|
||||
that checks for a new employee's name, and checks that the employee's salary is
|
||||
a positive value.
|
||||
The example shown demonstrates creating a trigger function named *emp_stamp*.
|
||||
|
||||
* Click the *Info* button (i) to access online help.
|
||||
* Click the *Save* button to save work.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Use the *View* dialog to define a view. The view is not physically materialized;
|
|||
the query is executed each time the view is referenced in a query.
|
||||
|
||||
The *View* dialog organizes the development of a View through the following
|
||||
dialog tabs: *General*, *Definition*, and *Security*". The *SQL* tab displays
|
||||
dialog tabs: *General*, *Definition*, *Code* and *Security*". The *SQL* tab displays
|
||||
the SQL code generated by dialog selections.
|
||||
|
||||
Click the *General* tab to begin.
|
||||
|
|
@ -49,7 +49,13 @@ Use the fields in the *Definition* tab to define properties of the view:
|
|||
* The *Cascaded* option specifies new rows are checked against the conditions
|
||||
of the view and all underlying base views.
|
||||
|
||||
* Use the workspace in the *Definition* field to write a query to create a view.
|
||||
Click the *Code* tab to continue.
|
||||
|
||||
.. image:: images/view_code.png
|
||||
:alt: View dialog code tab
|
||||
:align: center
|
||||
|
||||
Use the workspace in the *Code* tab to write a query to create a view.
|
||||
|
||||
Click the *Security* tab to continue.
|
||||
|
||||
|
|
@ -104,8 +110,7 @@ the *View* dialog:
|
|||
:alt: View dialog sql tab
|
||||
:align: center
|
||||
|
||||
The example shown demonstrates creating a view named *distributor_codes* that
|
||||
includes the content of the *code* column from the *distributors* table.
|
||||
The example shown demonstrates creating a view named *distributor_code*.
|
||||
|
||||
* Click the *Info* button (i) to access online help.
|
||||
* Click the *Save* button to save work.
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ define('pgadmin.node.function', [
|
|||
type: 'text', group: gettext('Definition'), mode: ['properties'],
|
||||
},{
|
||||
id: 'proargs', label: gettext('Arguments'), cell: 'string',
|
||||
type: 'text', group: gettext('Definition'), mode: ['properties', 'edit'],
|
||||
type: 'text', group: gettext('Definition'), mode: ['properties'],
|
||||
disabled: 'isDisabled',
|
||||
},{
|
||||
id: 'proargtypenames', label: gettext('Signature arguments'), cell:
|
||||
|
|
@ -244,8 +244,9 @@ define('pgadmin.node.function', [
|
|||
},{
|
||||
id: 'prosrc', label: gettext('Code'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
group: gettext('Definition'), deps: ['lanname'],
|
||||
control: Backform.SqlFieldControl,
|
||||
group: gettext('Code'), deps: ['lanname'],
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
extraClasses:['custom_height_css_class'],
|
||||
visible: function(m) {
|
||||
if (m.get('lanname') == 'c') {
|
||||
|
|
@ -324,7 +325,7 @@ define('pgadmin.node.function', [
|
|||
mode: ['properties'], group: gettext('Security'),
|
||||
},{
|
||||
id: 'arguments', label: gettext('Arguments'), cell: 'string',
|
||||
group: gettext('Arguments'), type: 'collection', canAdd: function(m){
|
||||
group: gettext('Definition'), type: 'collection', canAdd: function(m){
|
||||
return m.isNew();
|
||||
},
|
||||
canDelete: true, model: ArgumentModel, mode: ['create', 'edit'],
|
||||
|
|
|
|||
|
|
@ -179,9 +179,9 @@ define('pgadmin.node.trigger_function', [
|
|||
},{
|
||||
id: 'prosrc', label: gettext('Code'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'],
|
||||
group: gettext('Definition'), deps: ['lanname'],
|
||||
control: Backform.SqlFieldControl,
|
||||
extraClasses:['custom_height_css_class'],
|
||||
group: gettext('Code'), deps: ['lanname'],
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
visible: function(m) {
|
||||
if (m.get('lanname') == 'c') {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -97,9 +97,9 @@ define('pgadmin.node.edbfunc', [
|
|||
},{
|
||||
id: 'prosrc', label: gettext('Code'), cell: 'string',
|
||||
type: 'text', mode: ['properties'],
|
||||
group: gettext('Definition'),
|
||||
control: Backform.SqlFieldControl,
|
||||
extraClasses:['custom_height_css_class'],
|
||||
group: gettext('Code'),
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
visible: function(m) {
|
||||
if (m.get('lanname') == 'c') {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -144,12 +144,14 @@ define('pgadmin.node.package', [
|
|||
mode: ['properties', 'create', 'edit'],
|
||||
},{
|
||||
id: 'pkgheadsrc', label: gettext('Header'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Code'),
|
||||
control: Backform.SqlFieldControl,
|
||||
type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Header'),
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
},{
|
||||
id: 'pkgbodysrc', label: gettext('Body'), cell: 'string',
|
||||
type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Code'),
|
||||
control: Backform.SqlFieldControl,
|
||||
type: 'text', mode: ['properties', 'create', 'edit'], group: gettext('Body'),
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
},{
|
||||
id: 'acl', label: gettext('Privileges'), type: 'text',
|
||||
group: gettext('Security'), mode: ['properties'],
|
||||
|
|
|
|||
|
|
@ -480,7 +480,9 @@ define('pgadmin.node.trigger', [
|
|||
},{
|
||||
id: 'prosrc', label: gettext('Code'), group: gettext('Code'),
|
||||
type: 'text', mode: ['create', 'edit'], deps: ['tfunction'],
|
||||
control: 'sql-field', visible: true,
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
visible: true,
|
||||
disabled: function(m) {
|
||||
// We will enable it only when EDB PPAS and trigger function is
|
||||
// set to Inline EDB-SPL
|
||||
|
|
|
|||
|
|
@ -168,9 +168,10 @@ define('pgadmin.node.mview', [
|
|||
id: 'comment', label: gettext('Comment'), cell: 'string',
|
||||
type: 'multiline',
|
||||
},{
|
||||
id: 'definition', label:'Definition', cell: 'string',
|
||||
id: 'definition', label: gettext('Definition'), cell: 'string',
|
||||
type: 'text', mode: ['create', 'edit'], group: gettext('Definition'),
|
||||
control: Backform.SqlFieldControl, extraClasses:['sql_field_width_full'],
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
},{
|
||||
id: 'with_data', label: gettext('With data?'),
|
||||
group: gettext('Storage'), mode: ['edit', 'create'],
|
||||
|
|
|
|||
|
|
@ -151,9 +151,10 @@ define('pgadmin.node.view', [
|
|||
label: gettext('Cascaded'), value: 'cascaded',
|
||||
}],
|
||||
},{
|
||||
id: 'definition', label: gettext('Definition'), cell: 'string',
|
||||
type: 'text', mode: ['create', 'edit'], group: gettext('Definition'),
|
||||
control: Backform.SqlFieldControl,
|
||||
id: 'definition', label: gettext('Code'), cell: 'string',
|
||||
type: 'text', mode: ['create', 'edit'], group: gettext('Code'),
|
||||
tabPanelCodeClass: 'sql-code-control',
|
||||
control: Backform.SqlCodeControl,
|
||||
disabled: 'notInSchema',
|
||||
}, pgBrowser.SecurityGroupSchema, {
|
||||
// Add Privilege Control
|
||||
|
|
@ -188,7 +189,7 @@ define('pgadmin.node.view', [
|
|||
}
|
||||
if (_.isUndefined(field_def) || _.isNull(field_def) ||
|
||||
String(field_def).replace(/^\s+|\s+$/g, '') == '') {
|
||||
err['definition'] = gettext('Please enter view definition.');
|
||||
err['definition'] = gettext('Please enter view code.');
|
||||
errmsg = errmsg || err['definition'];
|
||||
this.errorModel.set('definition', errmsg);
|
||||
return errmsg;
|
||||
|
|
|
|||
|
|
@ -653,7 +653,7 @@ define([
|
|||
'<%=label%></a></li>',
|
||||
].join(' ')),
|
||||
'panel': _.template(
|
||||
'<div role="tabpanel" tabindex="-1" class="tab-pane <%=label%> pg-el-sm-12 pg-el-md-12 pg-el-lg-12 pg-el-12 fade" id="<%=cId%>" aria-labelledby="<%=hId%>"></div>'
|
||||
'<div role="tabpanel" tabindex="-1" class="tab-pane <%=label%> <%=tabPanelCodeClass%> pg-el-sm-12 pg-el-md-12 pg-el-lg-12 pg-el-12 fade" id="<%=cId%>" aria-labelledby="<%=hId%>"></div>'
|
||||
),
|
||||
},
|
||||
render: function() {
|
||||
|
|
@ -1889,6 +1889,7 @@ define([
|
|||
label: s.label || s.id,
|
||||
version_compatible: ver_in_limit,
|
||||
visible: visible,
|
||||
tabPanelCodeClass: '',
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
|
@ -1988,11 +1989,16 @@ define([
|
|||
// Create an array from the dictionary with proper required
|
||||
// structure.
|
||||
_.each(groups, function(val, key) {
|
||||
let tabPanelCodeClass = _.pluck(val, 'tabPanelCodeClass');
|
||||
if (tabPanelCodeClass) {
|
||||
tabPanelCodeClass = tabPanelCodeClass.join(' ').trim();
|
||||
}
|
||||
fields.push(
|
||||
_.extend(
|
||||
_.defaults(
|
||||
groupInfo[key] || {
|
||||
label: key,
|
||||
tabPanelCodeClass: tabPanelCodeClass,
|
||||
}, {
|
||||
version_compatible: true,
|
||||
visible: true,
|
||||
|
|
@ -2511,6 +2517,25 @@ define([
|
|||
},
|
||||
});
|
||||
|
||||
/*
|
||||
* Control For Code Mirror with FULL text area.
|
||||
*/
|
||||
Backform.SqlCodeControl = Backform.SqlFieldControl.extend({
|
||||
// Customize template to add new styles
|
||||
template: _.template([
|
||||
'<div class="pgadmin-controls pg-el-12 <%=extraClasses.join(\' \')%>">',
|
||||
' <textarea ',
|
||||
' class="<%=Backform.controlClassName%> " name="<%=name%>"',
|
||||
' maxlength="<%=maxlength%>" placeholder="<%-placeholder%>" <%=disabled ? "disabled" : ""%>',
|
||||
' rows=<%=rows%>',
|
||||
' <%=required ? "required" : ""%>><%-value%></textarea>',
|
||||
' <% if (helpMessage && helpMessage.length) { %>',
|
||||
' <span class="<%=Backform.helpMessageClassName%>"><%=helpMessage%></span>',
|
||||
' <% } %>',
|
||||
'</div>',
|
||||
].join('\n')),
|
||||
});
|
||||
|
||||
// We will use this control just as a annotate in Backform
|
||||
Backform.NoteControl = Backform.Control.extend({
|
||||
defaults: {
|
||||
|
|
|
|||
|
|
@ -518,6 +518,15 @@ fieldset.inline-fieldset > div {
|
|||
}
|
||||
}
|
||||
|
||||
.tab-pane.sql-code-control {
|
||||
@extend .tab-pane.SQL;
|
||||
& .pgadmin-control-group{
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.pgadmin-controls input[type="checkbox"]{
|
||||
margin-left: 0 !important;
|
||||
margin-top: 10px !important;
|
||||
|
|
|
|||