Hi,

I have created patch for "FTS Template" node in pgadmin4.
Please do review it and let me know in case anything is missing.

Regards,
Sanket Mehta
Sr Software engineer
Enterprisedb
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py
new file mode 100644
index 0000000..a571470
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/__init__.py
@@ -0,0 +1,430 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2016, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import json
+from flask import render_template, make_response, current_app, request, jsonify
+from flask.ext.babel import gettext
+from pgadmin.utils.ajax import make_json_response, \
+    make_response as ajax_response, internal_server_error
+from pgadmin.browser.utils import NodeView
+from pgadmin.browser.collection import CollectionNodeModule
+import pgadmin.browser.server_groups.servers.databases.schemas as schemas
+from pgadmin.utils.ajax import precondition_required
+from pgadmin.utils.driver import get_driver
+from config import PG_DEFAULT_DRIVER
+from functools import wraps
+from html import escape
+
+
+class FtsTemplateModule(CollectionNodeModule):
+    NODE_TYPE = 'fts_template'
+    COLLECTION_LABEL = gettext('Fts Templates')
+
+    def __init__(self, *args, **kwargs):
+        self.min_ver = None
+        self.max_ver = None
+        super(FtsTemplateModule, self).__init__(*args, **kwargs)
+
+    def get_nodes(self, gid, sid, did, scid):
+        """
+        Generate the collection node
+        """
+        yield self.generate_browser_collection_node(scid)
+
+    @property
+    def script_load(self):
+        """
+        Load the module script for fts template, when any of the schema node is
+        initialized.
+        """
+        return schemas.SchemaModule.NODE_TYPE
+
+
+blueprint = FtsTemplateModule(__name__)
+
+
+class FtsTemplateView(NodeView):
+    node_type = blueprint.node_type
+
+    parent_ids = [
+            {'type': 'int', 'id': 'gid'},
+            {'type': 'int', 'id': 'sid'},
+            {'type': 'int', 'id': 'did'},
+            {'type': 'int', 'id': 'scid'}
+            ]
+    ids = [
+            {'type': 'int', 'id': 'tid'}
+            ]
+
+    operations = dict({
+        'obj': [
+            {'get': 'properties', 'delete': 'delete', 'put': 'update'},
+            {'get': 'list', 'post': 'create'}
+        ],
+        'children': [{
+            'get': 'children'
+        }],
+        'delete': [{'delete': 'delete'}],
+        'nodes': [{'get': 'node'}, {'get': 'nodes'}],
+        'sql': [{'get': 'sql'}],
+        'msql': [{'get': 'msql'}, {'get': 'msql'}],
+        'stats': [{'get': 'statistics'}],
+        'dependency': [{'get': 'dependencies'}],
+        'dependent': [{'get': 'dependents'}],
+        'module.js': [{}, {}, {'get': 'module_js'}],
+        'getlexize': [{'get': 'getlexize'}, {'get': 'getlexize'}],
+        'getinit': [{'get': 'getinit'}, {'get': 'getinit'}],
+    })
+
+    def module_js(self):
+        """
+        This property defines (if javascript) exists for this node.
+        Override this property for your own logic.
+        """
+        return make_response(
+                render_template(
+                    "fts_template/js/fts_templates.js",
+                    _=gettext
+                    ),
+                200, {'Content-Type': 'application/x-javascript'}
+                )
+
+    def check_precondition(f):
+        """
+        This function will behave as a decorator which will checks
+        database connection before running view, it will also attaches
+        manager,conn & template_path properties to self
+        """
+        @wraps(f)
+        def wrap(*args, **kwargs):
+            # Here args[0] will hold self & kwargs will hold gid,sid,did
+            self = args[0]
+            self.manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(kwargs['sid'])
+            self.conn = self.manager.connection(did=kwargs['did'])
+            # If DB not connected then return error to browser
+            if not self.conn.connected():
+                return precondition_required(
+                    gettext(
+                            "Connection to the server has been lost!"
+                    )
+                )
+            self.template_path = 'fts_template/sql/'
+            return f(*args, **kwargs)
+
+        return wrap
+
+
+    @check_precondition
+    def list(self, gid, sid, did, scid):
+        SQL = render_template(
+            "/".join([self.template_path, 'properties.sql']),
+            scid=scid
+            )
+        status, res = self.conn.execute_dict(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        return ajax_response(
+                response=res['rows'],
+                status=200
+                )
+
+    @check_precondition
+    def nodes(self, gid, sid, did, scid):
+        res = []
+        SQL = render_template(
+            "/".join([self.template_path, 'properties.sql']),
+            scid=scid
+            )
+        status, rset = self.conn.execute_2darray(SQL)
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        for row in rset['rows']:
+            res.append(
+                    self.blueprint.generate_browser_node(
+                        row['oid'],
+                        row['tmplname'],
+                        icon="icon-fts_template"
+                    ))
+
+        return make_json_response(
+                data=res,
+                status=200
+                )
+
+    @check_precondition
+    def properties(self, gid, sid, did, scid, tid):
+        SQL = render_template(
+            "/".join([self.template_path, 'properties.sql']),
+            scid=scid,
+            tid=tid
+            )
+        status, res = self.conn.execute_dict(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=res)
+
+        return ajax_response(
+                response=res['rows'][0],
+                status=200
+                )
+
+    @check_precondition
+    def create(self, gid, sid, did, scid):
+        """
+        This function will creates new the fts_template object
+        """
+
+        required_args = [
+            'tmpllexize',
+            'schema',
+            'tmplname'
+        ]
+
+        data = request.form if request.form else json.loads(request.data.decode())
+        for arg in required_args:
+            if arg not in data:
+                return make_json_response(
+                    status=410,
+                    success=0,
+                    errormsg=gettext(
+                        "Couldn't find the required parameter (%s)." % arg
+                    )
+                )
+        try:
+            SQL = render_template("/".join([self.template_path, 'create.sql']),
+                                  data=data,
+                                  conn=self.conn,
+                                )
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            # we need oid to to add object in tree at browser, below sql will gives the same
+            SQL = render_template("/".join([self.template_path, 'properties.sql']),
+                                  name=data['tmplname']
+                                )
+            status, tid = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=tid)
+
+            return jsonify(
+                node=self.blueprint.generate_browser_node(
+                    tid,
+                    data['tmplname'],
+                    icon="icon-fts_template"
+                )
+            )
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+
+    @check_precondition
+    def update(self, gid, sid, did, scid, tid):
+        """
+        This function will update text search template object
+        """
+        data = request.form if request.form else json.loads(request.data.decode())
+        SQL = self.getSQL(gid, sid, did, scid, data, tid)
+        try:
+            if SQL and SQL.strip('\n') and SQL.strip(' '):
+                status, res = self.conn.execute_scalar(SQL)
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                return make_json_response(
+                    success=1,
+                    info="Cast updated",
+                    data={
+                        'id': tid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did,
+                        'scid': scid
+                    }
+                )
+            else:
+                return make_json_response(
+                    success=1,
+                    info="Nothing to update",
+                    data={
+                        'id': tid,
+                        'sid': sid,
+                        'gid': gid,
+                        'did': did,
+                        'scid': scid
+                    }
+                )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def delete(self, gid, sid, did, scid, tid):
+        """
+        This function will drop the fts_template object
+        """
+        # Below will decide if it's simple drop or drop with cascade call
+        if self.cmd == 'delete':
+            # This is a cascade operation
+            cascade = True
+        else:
+            cascade = False
+
+        try:
+            # Get name for template from tid
+            SQL = render_template("/".join([self.template_path, 'delete.sql']),
+                                  tid=tid)
+            status, res = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            # Drop fts template
+            result = res['rows'][0]
+            SQL = render_template("/".join([self.template_path, 'delete.sql']),
+                                  name=result['name'],
+                                  schema=result['schema'],
+                                  cascade=cascade
+                                  )
+            status, res = self.conn.execute_scalar(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            return make_json_response(
+                success=1,
+                info=gettext("Fts template dropped"),
+                data={
+                    'id': tid,
+                    'sid': sid,
+                    'gid': gid,
+                    'did': did,
+                    'scid': scid
+                }
+            )
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def msql(self, gid, sid, did, scid, tid=None):
+        """
+         This function returns modified SQL
+        """
+        data = request.args
+        SQL = self.getSQL(gid, sid, did, scid, data, tid)
+        if isinstance(SQL, str) and SQL and SQL.strip('\n') and SQL.strip(' '):
+            return make_json_response(
+                    data=SQL,
+                    status=200
+                    )
+        else:
+            return make_json_response(
+                    data="--modified SQL",
+                    status=200
+                    )
+
+    def getSQL(self, gid, sid, did, scid, data, tid=None):
+        """
+        This function will return SQL for model data
+        """
+        try:
+            if tid is not None:
+                SQL = render_template("/".join([self.template_path, 'properties.sql']),
+                                      tid=tid,
+                                      scid=scid
+                                      )
+                status, res = self.conn.execute_dict(SQL)
+
+                if not status:
+                    return internal_server_error(errormsg=res)
+
+                old_data = res['rows'][0]
+                SQL = render_template(
+                    "/".join([self.template_path, 'update.sql']),
+                    data=data, o_data=old_data
+                    )
+            else:
+                if 'tmpllexize' in data and 'tmplname' in data and 'schema' in data:
+                    SQL = render_template("/".join([self.template_path, 'create.sql']), data=data, conn=self.conn)
+                else:
+                    SQL = "-- incomplete definition"
+            return SQL
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+    @check_precondition
+    def getlexize(self, gid, sid, did, scid, cid=None):
+        data = request.args
+        SQL = render_template("/".join([self.template_path, 'functions.sql']),
+                              lexize=True)
+        status, rset = self.conn.execute_dict(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        res = [{'label': '', 'value': ''}]
+        # TODO: add schemaprefix to proname before adding it to value in res
+        for row in rset['rows']:
+            res.append({'label': row['proname'],
+                       'value': row['proname']})
+        return make_json_response(
+                    data=res,
+                    status=200
+                    )
+
+    @check_precondition
+    def getinit(self, gid, sid, did, scid, cid=None):
+        data = request.args
+        SQL = render_template("/".join([self.template_path, 'functions.sql']),
+                              init=True)
+        status, rset = self.conn.execute_dict(SQL)
+
+        if not status:
+            return internal_server_error(errormsg=rset)
+
+        # We have added this to map against '-' which is coming from properties
+        res = [{'label': '', 'value': '-'}]
+        # TODO: add schemaprefix to proname before adding it to value in res
+        for row in rset['rows']:
+            res.append({'label': row['proname'],
+                       'value': row['proname']})
+        return make_json_response(
+                    data=res,
+                    status=200
+                    )
+
+    @check_precondition
+    def sql(self, gid, sid, did, scid, tid):
+        """
+        This function will generate sql for sql panel
+        """
+        try:
+            SQL = render_template(
+                "/".join([self.template_path, 'properties.sql']),
+                tid=tid,
+                scid=scid
+                )
+            status, res = self.conn.execute_dict(SQL)
+            if not status:
+                return internal_server_error(errormsg=res)
+
+            result = res['rows'][0]
+            SQL = render_template("/".join([self.template_path, 'create.sql']),
+                                  data=result,
+                                  conn=self.conn,
+                                  is_sql=True
+                                  )
+            return ajax_response(response=SQL)
+
+        except Exception as e:
+            return internal_server_error(errormsg=str(e))
+
+FtsTemplateView.register_node_view(blueprint)
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/img/coll-fts_template.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/img/coll-fts_template.png
new file mode 100644
index 0000000000000000000000000000000000000000..fabd47da7ae27b04b0bfd38a7b1ee9f6c1a74d2c
GIT binary patch
literal 601
zcmY+9Ye-W86vyuj!!5?7zDS=7f?QnJEZv8iwXIEZ*mjEw%H7=uILpipL87b$mOaoY
zG^59ICOS;*K|&8hv}qE{A&!ucGBAp8clWjXUN`;JhyVGV1Lp_lv{kzg=yjWQ008J+
zPMb$%;lC8DQ|mUP!K;F=J_y-WCa0Pc@5*zzR4zBCD6@+4NtUN2X;PBj=W_GWZkwVc
zWch<AzUKL-I1VYwXB<By%TpNUmZUKhtrUb892b%08Ci}?(zqzT6~$3Oc+T^K9M{LP
zw=t|r6yJ#AD?u3H`54DNK@cm;cGGmLAiNZWVV)o0xM()}fMvTF<`%=;K+*ji*OSfO
zXW34M>7eOret#)NwPdsRSoRLXw9|AOMO~(-3nbZ`$%Op=GMc^u!)A&)55r(46ZH9t
z38IdoE|KIpl5EOk8VRDFAOh($o=&3+LQOz@UK8@Ty?}N33$6~@2IsM$O6O`EAM5t0
zO_$470Ts<5J~XUxtOtF59LHe{`S}eE>l)5RWAIXicVhB-Uu&D8O228Z^XA1!$H>+G
zyJb#mUa!MbdE9ZteNwX}Qs9a94)(<Qh8}A-&gKmyQ_1<c-Jm&72b|DB$SHpSuZL^%
zpB44T7vibJ;&@V940wM0S^B-a^8HtSaIAB*efUv})mI1s6I0UwKrb31UlSXe)DyRc
z>_<Z=9KtL}Bc=i{fhC}^#AF0ZAQNaY@3fdpw}Yh?5PZ0@Ble$g`V3l&H?Ij``Kq99
Yn=Rn3HDRXf@SrLHF1y<{w9gm*3#c75djJ3c

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/img/fts_template.png b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/static/img/fts_template.png
new file mode 100644
index 0000000000000000000000000000000000000000..eb780bf0bb0f5d777e8a72720b5ed0e2ad48bc45
GIT binary patch
literal 696
zcmY+CS4>j@6ozkcq>wQ5!GLk#CLzU3S)oQ!Yr$eFU<-t$cHKq-h(bd^Q2~h-MIjMo
zBO)RJ1T=0%>WGXeVM%<^_+&IudiTD!Ug61y|NQ4q&iC@?)TAUG@by{m0|0<;qE2g&
zJm8<?E2J5s@HYa0>`;n6HC~D{V`Wn#u^!KY$1^XAv!XaHik}2wQV_;?{=MCv=JCwg
z?M6|Yf}q2KFb+Y<JpTrQ^c?p>6lX;7qaaKO!Uvvz%k!fg_mbnDvg{+49p?FWJn!PT
zR~+|@WgoNb1BSV8vuSC%o99P3?m5doVcCZaGsrM~G<}z*Z&Oq|NjBSTI+h(`n0}h>
zq3JG)>Y%6=lDuiLs0iXJ!wfLYJ(|8lQMV|nl_VQU@;X6W!|}^Fei6f}Xu8vCjU&k>
zl58M|I)b=@<Ck#!0)|zX%}Nw4CCM8EQBM%HIPS#pY7DEyu(K#yhN2}1Qj8#lI9_A1
zM4{+uvl%p*6fj(1GKIqMaSS_;qGu4qfgq<4<OB@o!EmnIZFjqEZnt$+xwl3tROT=w
z83FZ=FLo(-pVVa*ORif|!bD!2v~(qE_oW8TSxqjWRxfwS*P1M=z1F2im-r=x?Q{Y$
z{<}AiR&>@6%eCr;WPOgta4;(&-EXUFOUO`XZ}&h~Uyt9KfZ6H!*@c<Ub1`7Gd^|9y
zwW*~!J0mM||H}OQKfgC_Xm2}`^EKFOaZ|_9Z*i~BiL%Oo%Fgfg)5EZHy!U6IQ=Q+I
ztuEI%EQTT<ZE%zV+`BCzbkDAsI`95tav4ziD`;WBxc%P;?Qq0rIBaGIq_P%4k^xFE
z98`oW6<~O(5>!P-s3N06!6+37b}WYV{Rb2j+H&n>%K#X=1W4DBDlmE(m~2cNkN_Yt
LK1n;MF;)Eq048yN

literal 0
HcmV?d00001

diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/js/fts_templates.js b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/js/fts_templates.js
new file mode 100644
index 0000000..7cc6ec5
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/js/fts_templates.js
@@ -0,0 +1,109 @@
+define(
+        ['jquery', 'underscore', 'underscore.string', 'pgadmin', 'pgadmin.browser', 'alertify', 'pgadmin.browser.collection'],
+function($, _, S, pgAdmin, pgBrowser, alertify) {
+
+  if (!pgBrowser.Nodes['coll-fts_template']) {
+    var fts_templates = pgAdmin.Browser.Nodes['coll-fts_template'] =
+      pgAdmin.Browser.Collection.extend({
+        node: 'fts_template',
+        label: '{{ _('FTS Templates') }}',
+        type: 'coll-fts_template'
+      });
+  };
+
+  if (!pgBrowser.Nodes['fts_template']) {
+    pgAdmin.Browser.Nodes['fts_template'] = pgAdmin.Browser.Node.extend({
+      parent_type: 'schema',
+      type: 'fts_template',
+      canDrop: true,
+      canDropCascade: true,
+      label: '{{ _('FTS Templates') }}',
+      hasSQL: true,
+      Init: function() {
+        /* Avoid mulitple registration of menus */
+        if (this.initialized)
+          return;
+
+        this.initialized = true;
+
+        pgBrowser.add_menus([{
+          name: 'create_fts_template_on_schema', node: 'schema', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('FTS Template...') }}',
+          icon: 'wcTabIcon icon-fts_template', data: {action: 'create'}
+          },{
+          name: 'create_fts_template_on_coll', node: 'coll-fts_template', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('FTS Template...') }}',
+          icon: 'wcTabIcon icon-fts_template', data: {action: 'create'}
+          },{
+          name: 'create_fts_template', node: 'fts_template', module: this,
+          applies: ['object', 'context'], callback: 'show_obj_properties',
+          category: 'create', priority: 4, label: '{{ _('FTS Template...') }}',
+          icon: 'wcTabIcon icon-fts_template', data: {action: 'create'}
+          }]);
+
+      },
+      model: pgAdmin.Browser.Node.Model.extend({
+        defaults: {
+          tmplname: undefined,
+          descrption: undefined,
+          schema: undefined,
+          tmplinit: undefined,
+          tmpllexize: undefined
+        },
+        schema: [{
+          id: 'tmplname', label: '{{ _('Name') }}', cell: 'string', group: 'Definition',
+          type: 'text',
+        },{
+          id: 'oid', label:'{{ _('Oid') }}', cell: 'string', group: 'Definition',
+          editable: false, type: 'text', disabled: true
+        },{
+          id: 'description', label:'{{ _('Comment') }}', cell: 'string', group: 'Properties',
+          type: 'multiline'
+        },{
+          id: 'tmplinit', label: '{{ _('Init')}}', group: 'Definition',
+          type: 'text', disabled: function(m) { return !m.isNew(); },
+          control: 'node-ajax-options', url: 'getinit'
+        },{
+          id: 'tmpllexize', label: '{{ _('Lexize')}}', group: 'Definition',
+          type: 'text', disabled: function(m) { return !m.isNew(); },
+          control: 'node-ajax-options', url: 'getlexize'
+        },{
+          id: 'schema', label: '{{ _('Schema')}}', cell: 'string', group: 'Definition',
+          type: 'text', mode: ['create','edit'], node: 'schema',
+          control: 'node-list-by-name'
+        }],
+        validate: function(keys){
+          var name = this.get('tmplname');
+          var lexize = this.get('tmpllexize');
+          var schema = this.get('schema');
+          if (_.isUndefined(name) || _.isNull(name) || String(name).replace(/^\s+|\s+$/g, '') == '') {
+            var msg = '{{ _('Name must be specified!') }}';
+            this.errorModel.set('name', msg);
+            return msg;
+          }
+          else if (_.isUndefined(lexize) || _.isNull(lexize) || String(lexize).replace(/^\s+|\s+$/g, '') == '') {
+            var msg = '{{ _('Lexize function must be selected!') }}';
+            this.errorModel.set('tmpllexize', msg);
+            return msg;
+          }
+          else if (_.isUndefined(schema) || _.isNull(schema) || String(schema).replace(/^\s+|\s+$/g, '') == '') {
+            var msg = '{{ _('Schema must be selected!') }}';
+            this.errorModel.set('schema', msg);
+            return msg;
+          }
+          else
+          {
+            this.errorModel.unset('tmpllexize');
+            this.errorModel.unset('schema');
+          }
+          this.trigger('on-status-clear');
+          return null;
+        }
+      })
+    });
+  }
+
+return pgBrowser.Nodes['coll-fts_template'];
+});
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/create.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/create.sql
new file mode 100644
index 0000000..462d5f8
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/create.sql
@@ -0,0 +1,19 @@
+
+
+{# CREATE TEXT SEARCH TEMPLATE Statement #}
+{% if data and data.schema and data.tmplname and data.tmpllexize %}
+{% if is_sql %}
+-- Text Search Template: {{conn|qtIdent(data.schema)}}.{{conn|qtIdent(data.tmplname)}}
+
+-- DROP TEXT SEARCH TEMPLATE {{conn|qtIdent(data.schema)}}.{{conn|qtIdent(data.tmplname)}}
+{% endif %}
+
+CREATE TEXT SEARCH TEMPLATE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.tmplname) }} (
+{% if data.tmplinit and data.tmplinit != '-'%}  INIT = {{data.tmplinit}}{% endif %},
+  LEXIZE = {{data.tmpllexize}}
+);
+{# Description for TEXT SEARCH TEMPLATE #}
+{% if data.description %}
+COMMENT ON TEXT SEARCH TEMPLATE {{ conn|qtIdent(data.schema) }}.{{ conn|qtIdent(data.tmplname) }}
+      IS {{ data.description|qtLiteral }};
+{% endif %}{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/delete.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/delete.sql
new file mode 100644
index 0000000..ac11ac9
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/delete.sql
@@ -0,0 +1,20 @@
+{# FETCH TEXT SEARCH TEMPLATE NAME Statement #}
+{% if tid %}
+  SELECT
+    t.tmplname AS name,
+    (SELECT
+        nspname
+     FROM
+        pg_namespace
+     WHERE
+        oid = t.tmplnamespace) as schema
+  FROM
+    pg_ts_template t LEFT JOIN pg_description d
+  ON d.objoid=t.oid AND d.classoid='pg_ts_template'::regclass
+  WHERE
+    t.oid = {{tid}}::OID;
+{% endif %}
+{# DROP TEXT SEARCH TEMPLATE Statement #}
+{% if schema and name %}
+DROP TEXT SEARCH TEMPLATE {{conn|qtIdent(schema)}}.{{conn|qtIdent(name)}} {% if cascade %}CASCADE{%endif%};
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/functions.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/functions.sql
new file mode 100644
index 0000000..73ce9e2
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/functions.sql
@@ -0,0 +1,22 @@
+{# FETCH lexize functions for TEXT SEARCH TEMPLATE #}
+{% if lexize %}
+SELECT
+    proname, nspname
+FROM
+    pg_proc JOIN pg_namespace n ON n.oid=pronamespace
+WHERE
+    prorettype=2281
+    AND proargtypes='2281 2281 2281 2281'
+ORDER BY proname;
+{% endif %}
+
+{# FETCH init functions for TEXT SEARCH TEMPLATE #}
+{% if init %}
+SELECT
+    proname, nspname
+FROM
+    pg_proc JOIN pg_namespace n ON n.oid=pronamespace
+WHERE
+    prorettype=2281 and proargtypes='2281'
+ORDER BY proname;
+{% endif %}
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/properties.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/properties.sql
new file mode 100644
index 0000000..bcc11f0
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/properties.sql
@@ -0,0 +1,37 @@
+{# Get OID for FTS TEMPLATE #}
+{% if name %}
+SELECT
+    tmpl.oid
+FROM
+    pg_ts_template tmpl
+WHERE
+    tmpl.tmplname = {{name|qtLiteral}}
+{# FETCH properties for FTS TEMPLATE #}
+{% else %}
+
+SELECT
+    tmpl.oid,
+    tmpl.tmplname,
+    tmpl.tmplinit,
+    tmpl.tmpllexize,
+    description,
+    (SELECT
+        nspname
+     FROM
+        pg_namespace
+     WHERE
+        oid = tmpl.tmplnamespace
+    ) AS schema
+FROM
+    pg_ts_template tmpl LEFT OUTER JOIN pg_description des
+ON
+    (des.objoid=tmpl.oid AND des.classoid='pg_ts_template'::regclass)
+WHERE
+    tmpl.tmplnamespace = {{scid}}::OID
+{% if tid %}
+    AND tmpl.oid={{tid}}::OID
+{% endif %}
+ORDER BY
+tmpl.tmplname
+
+{% endif %}
\ No newline at end of file
diff --git a/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/update.sql b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/update.sql
new file mode 100644
index 0000000..d2fdc45
--- /dev/null
+++ b/web/pgadmin/browser/server_groups/servers/databases/schemas/fts_templates/templates/fts_template/sql/update.sql
@@ -0,0 +1,15 @@
+{# UPDATE NAME for TEXT SEARCH TEMPLATE statement #}
+{% if data %}
+{% if data.tmplname and data.tmplname != o_data.tmplname %}
+  ALTER TEXT SEARCH TEMPLATE {{conn|qtIdent(o_data.schema)}}.{{conn|qtIdent(o_data.tmplname)}}
+    RENAME TO {{data.tmplname}};
+{% endif %}
+{% if data.schema and data.schema != o_data.schema %}
+  ALTER TEXT SEARCH TEMPLATE {{conn|qtIdent(o_data.schema)}}.{{conn|qtIdent(o_data.tmplname)}}
+    SET SCHEMA {{data.schema}};
+{% endif %}
+{% if data.description and data.description != o_data.description %}
+  COMMENT ON TEXT SEARCH TEMPLATE {{conn|qtIdent(o_data.schema)}}.{{conn|qtIdent(o_data.tmplname)}}
+    IS {{ data.description|qtLiteral }};
+{% endif %}
+{% endif %}
\ No newline at end of file
-- 
Sent via pgadmin-hackers mailing list (pgadmin-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to