Hello,

please review attached patches which extend topology graph functionality. First two add possibility to create agreement using mouse and the third one adds 'Autogenerated' placeholder.


0047,48: https://fedorahosted.org/freeipa/ticket/5648

0050: https://fedorahosted.org/freeipa/ticket/5867

--

Pavel^3 Vomacka

From e7d132f85c8cd922cce8265d4e04832476f9d2e1 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Mon, 13 Jun 2016 10:21:25 +0200
Subject: [PATCH 1/3] Add creating a segment using mouse

Create new semicircles around the node after mouseover. These work as buttons
to create arrow and after clicking on another node the Add topology segment dialog
is opened. Also selecting segment works, if the segment already exists then
the segment is selected instead of opening the dialog.

https://fedorahosted.org/freeipa/ticket/5648
---
 install/ui/less/widgets.less             |  58 ++++--
 install/ui/src/freeipa/topology_graph.js | 347 ++++++++++++++++++++++++++++++-
 2 files changed, 381 insertions(+), 24 deletions(-)

diff --git a/install/ui/less/widgets.less b/install/ui/less/widgets.less
index 0f9bc8c171d5c35d955c6b55d2e95ee105c35159..c1f713303b80343206d2267baf2be745b4fa7d5e 100644
--- a/install/ui/less/widgets.less
+++ b/install/ui/less/widgets.less
@@ -150,41 +150,59 @@ tbody:empty { display: none; }
 
 .topology-view {
     svg {
-      background-color: #FFF;
-      cursor: default;
-      -webkit-user-select: none;
-      -moz-user-select: none;
-      -ms-user-select: none;
-      -o-user-select: none;
-      user-select: none;
+        background-color: #FFF;
+        cursor: default;
+        -webkit-user-select: none;
+        -moz-user-select: none;
+        -ms-user-select: none;
+        -o-user-select: none;
+        user-select: none;
     }
 
+
     path.link {
-      fill: none;
-      stroke-width: 4px;
-      cursor: pointer;
+        fill: none;
+        stroke: #000;
+        stroke-width: 4px;
+        cursor: pointer;
+        .dragline {
+            pointer-events: none;
+        }
+    }
+
+    .plus {
+        font-size: .9em;
+        fill: #fff;
+    }
+
+    .adder_label {
+        font-weight: bold;
+    }
+
+    path.adder {
+        cursor: pointer;
+    }
+
+    .selected {
+        stroke-dasharray: 10,2;
     }
 
     .marker {
         stroke: rgba(0, 0, 0);
     }
 
-    path.link.selected {
-      stroke-dasharray: 10,2;
-    }
-
     circle.node {
-      stroke-width: 1.5px;
-      cursor: pointer;
+        stroke-width: 1.5px;
+        cursor: pointer;
     }
 
     text {
-      font: 16px sans-serif;
-      pointer-events: none;
+        font: 16px sans-serif;
+        pointer-events: none;
     }
 
     text.id {
-      text-anchor: middle;
-      font-weight: bold;
+        text-anchor: middle;
+        font-weight: bold;
     }
 }
diff --git a/install/ui/src/freeipa/topology_graph.js b/install/ui/src/freeipa/topology_graph.js
index 332411f943770a8e1833b698ee28026e2382bb76..5410f242b1422c86f36041042a7eb77e2ff629a3 100644
--- a/install/ui/src/freeipa/topology_graph.js
+++ b/install/ui/src/freeipa/topology_graph.js
@@ -29,13 +29,21 @@ var topology_graph = {
 topology_graph.TopoGraph = declare([Evented], {
     width: 960,
     height: 500,
+    _adder_anim_duration: 200,
+    _adder_inner_radius: 15,
+    _adder_outer_radius: 30,
     _colors: d3.scale.category10(),
     _svg : null,
     _path: null,
     _circle: null,
 
+    _create_agreement: null,
     _selected_link: null,
     _mousedown_link: null,
+    _source_node: null,
+    _source_node_html: null,
+    _target_node: null,
+    _drag_line: null,
 
     /**
      * Nodes - IPA servers
@@ -115,31 +123,89 @@ topology_graph.TopoGraph = declare([Evented], {
                 node.x = Number(this._get_local_storage_attr(node.id, 'x'));
                 node.y = Number(this._get_local_storage_attr(node.id, 'y'));
             }
+            node.ca_adder = d3.svg.arc()
+                .innerRadius(this._adder_inner_radius)
+                .outerRadius(this._adder_inner_radius)
+                .startAngle(2 * (Math.PI/180))
+                .endAngle(178 * (Math.PI/180));
+
+            node.domain_adder = d3.svg.arc()
+                .innerRadius(this._adder_inner_radius)
+                .outerRadius(this._adder_inner_radius)
+                .startAngle(182 * (Math.PI/180))
+                .endAngle(358 * (Math.PI/180));
+
+            node.drag_mode = false;
         }
 
         this._init_layout();
         this._define_shapes();
 
         // handles to link and node element groups
+        // the order of adding shapes is important because of order of showing
+        // them
         this._path = this._svg.append('svg:g')
                               .classed('shapes', true)
                               .selectAll('path');
 
+        this._drag_line = this._svg.append('svg:g')
+            .classed('shapes', true)
+            .append('path')
+            .style('marker-end', 'url(#end-arrow)')
+            .attr('class', 'link dragline hidden')
+            .attr('d', 'M0,0L0,0')
+            .on('click', function() {
+                d3.event.preventDefault();
+                d3.event.stopPropagation();
+
+                this._create_agreement = false;
+                this.reset_mouse_vars();
+
+                this._drag_line
+                    .classed('hidden', true)
+                    .style('marker-end', '');
+
+                this.restart();
+
+            }.bind(this));
+
         this._circle = this._svg.append('svg:g')
                            .classed('shapes', true)
                            .selectAll('g');
 
         this._selected_link = null;
-        this._mouseup_node = null;
         this._mousedown_link = null;
+        this._selected_node = null;
+        this._source_node = null;
+        this._target_node = null;
         this.restart();
     },
 
     _create_svg: function(container) {
+        var self = this;
+
         this._svg = d3.select(container[0]).
             append('svg').
             attr('width', this.width).
-            attr('height', this.height);
+            attr('height', this.height).
+            on('mousemove', mousemove);
+
+            function mousemove(d) {
+                if (!self._source_node && !self._create_agreement) return;
+
+                var translate = self._get_stored_transformation();
+                var x = self._source_node.x;
+                var y = self._source_node.y;
+
+                var mouse_x = x + d3.mouse(self._source_node_html)[0];
+                var mouse_y = y + d3.mouse(self._source_node_html)[1];
+
+                // update drag line
+                self._drag_line.attr('d', 'M' + x + ',' + y + 'L' + mouse_x + ',' + mouse_y);
+
+                self.restart();
+            }
+
     },
 
     _init_layout: function() {
@@ -342,11 +408,28 @@ topology_graph.TopoGraph = declare([Evented], {
             this._append_suffix_hint(suffix, x, y);
             y += 30;
         }
-
-        this._circle_color = this._colors(1);
     },
 
     /**
+     * Returns lenght of string with set class in pixels
+     */
+     _count_string_size: function(str, cls) {
+         if (!str) return 0;
+
+         cls = cls || '';
+
+         var node = this._svg.append('text')
+            .classed(cls, true)
+            .text(str);
+
+         var length = node.node().getComputedTextLength();
+
+         node.remove();
+
+         return length;
+     },
+
+    /**
      * Restart the simulation to reflect changes in data/state
      */
     restart: function() {
@@ -422,6 +505,8 @@ topology_graph.TopoGraph = declare([Evented], {
             .on("dragend", dragended);
 
         function dragstarted(d) {
+            d.drag_mode = true;
+            hide_semicircles.bind(this, d)();
             d3.event.sourceEvent.stopPropagation();
             // Store the original value of fixed and set the node fixed.
             d.fixed = d.fixed << 1;
@@ -437,11 +522,213 @@ topology_graph.TopoGraph = declare([Evented], {
         }
 
         function dragended(d) {
+            d.drag_mode = false;
             // Restore old value of fixed.
             d.fixed = d.fixed >> 1;
             self._layout.resume();
         }
 
+        function add_labels(type, color, adder_group) {
+            var label_radius = 3;
+
+            var plus = adder_group
+                .append('text')
+                .classed('plus', true)
+                .classed(type + '_plus', true)
+                .text('\uf067');
+
+            var label = adder_group.append('path')
+                    .attr('id', type + '_label');
+
+            if (type === 'ca') {
+                plus.attr('dx', '18')
+                    .attr('dy', '4');
+                var adder_label = adder_group.append('text')
+                    .append('textPath')
+                        .classed('adder_label', true)
+                        .style('fill', color)
+                        .attr('xlink:href', '#' + type + '_label')
+                        .text(type);
+
+                var str_size = self._count_string_size(type, 'adder_label');
+                var str_translate = str_size + self._adder_outer_radius + 3;
+                label.attr('d', 'M 33 3 L ' + str_translate + ' 3');
+
+                adder_group.insert('rect', 'text')
+                    .attr('x', '33')
+                    .attr('y', '-11')
+                    .attr('rx', label_radius)
+                    .attr('ry', label_radius)
+                    .attr('width', str_size)
+                    .attr('height', '18')
+                    .style("fill", "white");
+            }
+            else {
+                plus.attr('dx', '-26')
+                    .attr('dy', '4');
+                adder_label = adder_group.append('text')
+                    .append('textPath')
+                        .classed('adder_label', true)
+                        .style('fill', color)
+                        .attr('xlink:href', '#' + type + '_label')
+                        .text(type);
+
+                str_size = self._count_string_size(type, 'adder_label');
+                str_translate = str_size + self._adder_outer_radius + 3;
+                label.attr('d', 'M -' + str_translate + ' 3 L -33 3');
+
+                adder_group.insert('rect', 'text')
+                    .attr('x', '-'+str_translate)
+                    .attr('y', '-11')
+                    .attr('rx', label_radius)
+                    .attr('ry', label_radius)
+                    .attr('width', str_size)
+                    .attr('height', '18')
+                    .style('fill', 'white');
+            }
+        }
+
+        function create_semicircle(d, type) {
+            var color = d3.rgb(self._colors(type)).toString();
+            var adder_group = d3.select(this).select('g');
+            var scale = '1.05';
+
+            adder_group.append("path")
+                .classed(type+'_adder', true)
+                .classed('adder', true)
+                .attr("d", d[type + '_adder'])
+                .attr("fill", color)
+                .on('mouseover', function(d) {
+                    window.clearTimeout(d._timeout_hide);
+
+                    d3.select(this).attr('transform', 'scale('+scale+')');
+                    adder_group.select('text.' + type + '_plus')
+                        .attr('transform', 'scale('+scale+')');
+                })
+                .on('mouseout', function(d) {
+                    d3.select(this).attr('transform', '');
+                    adder_group.select('text.' + type + '_plus')
+                        .attr('transform', '');
+                })
+                .on('click', function(d) {
+                    d3.event.preventDefault();
+                    d3.event.stopPropagation();
+                    self.emit('link-selected', { link: null });
+
+                    hide_semicircles.bind(this, d)();
+
+                    // select node
+                    if (!self._source_node) {
+                        self._source_node = d;
+                        self._source_node_html = d3.select(this)
+                                                    .select('circle').node();
+                        self._create_agreement = true;
+                    }
+
+                    self._selected_link = null;
+
+                    var translate = self._get_stored_transformation();
+                    var x = self._source_node.x;
+                    var y = self._source_node.y;
+
+                    // add position of node + translation of whole graph + relative
+                    // position of the mouse
+                    var mouse_x = d.x + d3.mouse(this)[0];
+                    var mouse_y = d.y + d3.mouse(this)[1];
+
+                    // reposition drag line
+                    self._drag_line
+                        .style('marker-end', 'url(#' + type + '-end-arrow)')
+                        .style('stroke', color)
+                        .classed('hidden', false)
+                        .attr('suffix', type)
+                        .attr('d', 'M' + x + ',' + y +
+                                'L' + mouse_x + ',' + mouse_y);
+
+                    self.restart();
+                }.bind(this))
+                .on('mousedown.drag', function() {
+                    d3.event.preventDefault();
+                    d3.event.stopPropagation();
+                })
+                .transition()
+                    .duration(self._adder_anim_duration)
+                    .attr("d", d[type + '_adder']
+                        .outerRadius(self._adder_outer_radius))
+                    .each('end', function() {
+                        add_labels(type, color, adder_group);
+                    });
+        }
+
+        function show_semicircles(d) {
+
+            if(!d3.select(this).select('g path').empty()) return;
+
+            if (!d.drag_mode && !self._create_agreement) {
+
+                // append invisible circle which covers spaces between node
+                // and adders it prevents hiding adders when mouse is on the space
+                d3.select(this).append('g')
+                    .append('circle')
+                    .attr('r', self._adder_outer_radius)
+                    .style('opacity', 0);
+                create_semicircle.bind(this, d, 'ca')();
+
+                create_semicircle.bind(this, d, 'domain')();
+
+                //move the identification text
+                d3.select(this).select('text')
+                    .transition()
+                        .duration(self._adder_anim_duration)
+                        .attr('dy', '45');
+            }
+        }
+
+        function hide_semicircles(d) {
+            var curr_nod = d3.select(this);
+            curr_nod.selectAll('.plus,.adder_label,rect')
+                .transition()
+                    .ease('exp')
+                    .duration(100)
+                    .style('font-size', '0px')
+                    .remove();
+            curr_nod.select('path.domain_adder')
+                .transition()
+                    .attr("d", d.domain_adder
+                        .outerRadius(self._adder_inner_radius))
+                    .duration(self._adder_anim_duration);
+            curr_nod.select('path.ca_adder')
+                .transition()
+                    .attr("d", d.ca_adder
+                        .outerRadius(self._adder_inner_radius))
+                    .duration(self._adder_anim_duration);
+            curr_nod.select('g')
+                .transition()
+                    .duration(self._adder_anim_duration)
+                    .remove();
+            curr_nod.select('text')
+                .transition()
+                    .attr('dy', '30')
+                    .duration(self._adder_anim_duration);
+        }
+
+        function is_suffix_shown(suffix) {
+            var links = self._source_node.targets[self._target_node.id];
+
+            if (!links) return false;
+
+            for (var i=0, l=links.length; i<l; i++) {
+                var link = links[i];
+                if (link.suffix.cn[0] === suffix) {
+                    self._selected_link = link;
+                    self.emit('link-selected', { link: link });
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
         // add new nodes
         var g = this._circle.enter()
             .append('svg:g')
@@ -453,6 +740,49 @@ topology_graph.TopoGraph = declare([Evented], {
                 d.fixed = d.fixed ^ 1;
                 self._layout.resume();
             })
+            .on('mouseover', function(d) {
+                window.clearTimeout(d._timeout_hide);
+                show_semicircles.bind(this, d)();
+                d3.select('circle.cover').classed('cover', true);
+            })
+            .on('mouseout', function(d) {
+                d._timeout_hide = window.setTimeout(hide_semicircles
+                                                        .bind(this, d), 200);
+            })
+            .on('click', function(d) {
+                if (!self._create_agreement) return;
+
+                d3.event.preventDefault();
+                d3.event.stopPropagation();
+
+                if (self._source_node !== d) {
+                    self._target_node = d;
+                    var source = self._source_node;
+                    var target = self._target_node;
+                    var suffix = self._drag_line.attr('suffix');
+                    var direction = 'left';
+                    var link = {
+                        source: source,
+                        target: target,
+                        suffix: suffix,
+                        left: false,
+                        right: false
+                    };
+
+                    if (!is_suffix_shown(suffix)) {
+                        link[direction] = true;
+                        self.emit('add-agreement', link);
+                    }
+                }
+
+                self._drag_line
+                    .classed('hidden', true)
+                    .attr('suffix', '')
+                    .style('marker-end', '');
+
+                self.restart();
+                self.reset_mouse_vars();
+            })
             .call(drag);
 
         g.append('svg:circle')
@@ -488,6 +818,15 @@ topology_graph.TopoGraph = declare([Evented], {
             .attr("transform", transform);
     },
 
+    reset_mouse_vars: function() {
+        this._source_node = null;
+        this._source_node_html = null;
+        this._target_node = null;
+        this._mousedown_link = null;
+        this._create_agreement = null;
+
+    },
+
     resize: function(height, width) {
         if (!(isNaN(height) || isNaN(width))) {
             this.height = height < 0 ? 0 : height;
-- 
2.5.5

From aae386fdc4d7a7050b406732d8abb65a28781544 Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Mon, 13 Jun 2016 10:27:52 +0200
Subject: [PATCH 2/3] Add listener which opens add segment dialog

The event is emited by clicking on the second node when adding segment by mouse.
The listener opens dialog and prefill values.

Part of: https://fedorahosted.org/freeipa/ticket/5648
---
 install/ui/src/freeipa/topology.js | 182 ++++++++++++++++++++++---------------
 1 file changed, 108 insertions(+), 74 deletions(-)

diff --git a/install/ui/src/freeipa/topology.js b/install/ui/src/freeipa/topology.js
index 290dc3825e1e7938a131b81a5e76764371e007a1..ddbea80eea2613202afb22e1a73c01adbc1c6420 100644
--- a/install/ui/src/freeipa/topology.js
+++ b/install/ui/src/freeipa/topology.js
@@ -684,6 +684,12 @@ topology.TopologyGraphFacet = declare([Facet, ActionMixin, HeaderMixin], {
             this.set_selected_link(data.link);
         }.bind(this));
 
+        on(graph, 'add-agreement', function(link) {
+            var dialog = topology.create_add_dialog();
+            dialog.open();
+            dialog.prefill_dialog(link);
+        });
+
         on(this, 'hide', function () {
             $(window).off('resize', null, listener);
         });
@@ -718,6 +724,106 @@ topology.TopologyGraphFacet = declare([Facet, ActionMixin, HeaderMixin], {
     }
 });
 
+
+/**
+ * Creates segment adder dialog according to spec.
+ *
+ * @param spec {Object}
+ */
+topology.create_add_dialog = function(spec) {
+
+    spec = spec || {};
+
+    spec.entity = spec.entity || 'topologysegment';
+
+    var entity = reg.entity.get('topologysegment');
+    var title = text.get('@i18n:dialogs.add_title');
+    var label = entity.metadata.label_singular;
+    spec.title = title.replace('${entity}', label);
+
+    spec.fields = spec.fields || [
+        {
+            name: 'cn',
+            required: false
+        },
+        {
+            $type: 'entity_select',
+            name: 'suffix',
+            label: '@mo:topologysuffix.label_singular',
+            other_entity: 'topologysuffix',
+            other_field: 'cn',
+            z_index: 3,
+            required: true
+        },
+        {
+            $type: 'entity_select',
+            name: 'iparepltoposegmentleftnode',
+            other_entity: 'server',
+            other_field: 'cn',
+            z_index: 2
+        },
+        {
+            $type: 'entity_select',
+            name: 'iparepltoposegmentrightnode',
+            other_entity: 'server',
+            other_field: 'cn',
+            z_index: 1
+        }
+    ];
+
+
+    var that = IPA.entity_adder_dialog(spec);
+
+    that.init = function() {
+        that.added.attach(that.on_success);
+    };
+
+    that.show_edit_page = function(entity, result) {
+        var suffix = this.fields.get_field('suffix').save()[0];
+        var cn = result.cn[0];
+        navigation.show_entity(entity.name, 'default', [suffix, cn]);
+    };
+
+    that.create_add_command = function(record) {
+
+        var args = [this.fields.get_field('suffix').save()[0]];
+        var cn = this.fields.get_field('cn').save()[0];
+        if (cn) args.push(cn);
+
+        var options = {
+            'iparepltoposegmentleftnode':
+                this.fields.get_field('iparepltoposegmentleftnode').save()[0],
+            'iparepltoposegmentrightnode':
+                this.fields.get_field('iparepltoposegmentrightnode').save()[0]
+        };
+
+        var command = rpc.command({
+            entity: this.entity.name,
+            method: this.method,
+            retry: this.retry,
+            args: args,
+            options: options
+        });
+
+        return command;
+    };
+
+
+    that.on_success = function(data) {
+        that.facet.refresh();
+    };
+
+    that.prefill_dialog = function(link) {
+        that.get_field('iparepltoposegmentleftnode').set_value([link.source.id]);
+        that.get_field('iparepltoposegmentrightnode').set_value([link.target.id]);
+        that.get_field('suffix').set_value([link.suffix]);
+    };
+
+    that.init();
+
+    return that;
+};
+
 /**
  * Shows topology segment adder dialog with suffix select
  *
@@ -735,84 +841,11 @@ topology.add_segment_action = function(spec) {
 
     that.execute_action = function(facet, on_success, on_error) {
 
-        that.facet = facet;
-
-        var entity = reg.entity.get('topologysegment');
-        var title = text.get('@i18n:dialogs.add_title');
-        var label = entity.metadata.label_singular;
-        title = title.replace('${entity}', label);
-
-        var dialog = IPA.entity_adder_dialog({
-            entity: 'topologysegment',
-            title: title,
-            fields: [
-                {
-                    name: 'cn',
-                    required: false
-                },
-                {
-                    $type: 'entity_select',
-                    name: 'suffix',
-                    label: '@mo:topologysuffix.label_singular',
-                    other_entity: 'topologysuffix',
-                    other_field: 'cn',
-                    z_index: 3,
-                    required: true
-                },
-                {
-                    $type: 'entity_select',
-                    name: 'iparepltoposegmentleftnode',
-                    other_entity: 'server',
-                    other_field: 'cn',
-                    z_index: 2
-                },
-                {
-                    $type: 'entity_select',
-                    name: 'iparepltoposegmentrightnode',
-                    other_entity: 'server',
-                    other_field: 'cn',
-                    z_index: 1
-                }
-            ]
-        });
-        dialog.added.attach(that.on_success);
-
-        dialog.show_edit_page = function(entity, result) {
-            var suffix = this.fields.get_field('suffix').save()[0];
-            var cn = result.cn[0];
-            navigation.show_entity(entity.name, 'default', [suffix, cn]);
-        };
-
-        dialog.create_add_command = function(record) {
-
-            var args = [this.fields.get_field('suffix').save()[0]];
-            var cn = this.fields.get_field('cn').save()[0];
-            if (cn) args.push(cn);
-
-            var options = {
-                'iparepltoposegmentleftnode':
-                    this.fields.get_field('iparepltoposegmentleftnode').save()[0],
-                'iparepltoposegmentrightnode':
-                    this.fields.get_field('iparepltoposegmentrightnode').save()[0]
-            };
-
-            var command = rpc.command({
-                entity: this.entity.name,
-                method: this.method,
-                retry: this.retry,
-                args: args,
-                options: options
-            });
-
-            return command;
-        };
+        var dialog = topology.create_add_dialog();
 
         dialog.open();
     };
 
-    that.on_success = function(data) {
-        that.facet.refresh();
-    };
 
     return that;
 };
@@ -1109,6 +1142,7 @@ topology.TopologyGraphWidget = declare([Stateful, Evented], {
         }
 
         forward('link-selected');
+        forward('add-agreement');
     },
 
     _update_view: function() {
-- 
2.5.5

From 21538591605a8edf1583aef2743860a8cfc4e9be Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Mon, 13 Jun 2016 10:29:49 +0200
Subject: [PATCH 3/3] Add placeholder to add segment dialog

'Autogenerated' placeholder is shown when adding new segment.

https://fedorahosted.org/freeipa/ticket/5867
---
 install/ui/src/freeipa/topology.js | 1 +
 install/ui/test/data/ipa_init.json | 1 +
 ipaserver/plugins/internal.py      | 1 +
 3 files changed, 3 insertions(+)

diff --git a/install/ui/src/freeipa/topology.js b/install/ui/src/freeipa/topology.js
index ddbea80eea2613202afb22e1a73c01adbc1c6420..bde278f514363a71151ca6d4648f0206000bb64b 100644
--- a/install/ui/src/freeipa/topology.js
+++ b/install/ui/src/freeipa/topology.js
@@ -744,6 +744,7 @@ topology.create_add_dialog = function(spec) {
     spec.fields = spec.fields || [
         {
             name: 'cn',
+            placeholder: '@i18n:objects.topology.autogenerated',
             required: false
         },
         {
diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json
index 4ccf49f889f57eb28f11d8ebe701fac47d166879..277fe9f2740361c6d9d0bd53c296e6323a73117b 100644
--- a/install/ui/test/data/ipa_init.json
+++ b/install/ui/test/data/ipa_init.json
@@ -590,6 +590,7 @@
                             "user": "Who"
                         },
                         "topology": {
+                            "autogenerated": "Autogenerated",
                             "segment_details": "Segment details",
                             "replication_config": "Replication configuration",
                             "insufficient_domain_level" : "Managed topology requires minimal domain level ${domainlevel}"
diff --git a/ipaserver/plugins/internal.py b/ipaserver/plugins/internal.py
index c44c260f542428a76ff81c7119efefef4b5da492..a718dfe4ed65ee0c690e4ea6ffa1ea7f649f597d 100644
--- a/ipaserver/plugins/internal.py
+++ b/ipaserver/plugins/internal.py
@@ -729,6 +729,7 @@ class i18n_messages(Command):
                 "user": _("Who"),
             },
             "topology": {
+                "autogenerated": _("Autogenerated"),
                 "segment_details": _("Segment details"),
                 "replication_config": _("Replication configuration"),
                 "insufficient_domain_level" : _("Managed topology requires minimal domain level ${domainlevel}"),
-- 
2.5.5

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to