[Rt-commit] rt branch, 4.6/lifecycle-ui-dev, repushed

Craig Kaiser craig at bestpractical.com
Thu Dec 5 09:12:58 EST 2019


The branch 4.6/lifecycle-ui-dev was deleted and repushed:
       was 69448e40f2d4b6b34846128d94c41438e2ff8c36
       now a62f12eca6b3838acf3630e4992a14c19269b9d0

1: 69448e40f2 ! 1: a62f12eca6 Core Lifecycle-UI
    @@ -856,12 +856,14 @@
     +<script type="text/javascript" src="<%RT->Config->Get('WebPath')%>/static/js/farbtastic.js"></script>
     +
     +<form action="<%RT->Config->Get('WebPath')%>/Admin/Lifecycles/Modify.html" name="ModifyLifecycle" method="post" enctype="multipart/form-data">
    -+<input type="hidden" class="hidden" name="Name" value="<% $LifecycleObj->Name %>" />
    -+<input type="hidden" class="hidden" name="Type" value="<% $LifecycleObj->Type %>" />
    -+
    -+<& /Elements/Lifecycle/Graph, Lifecycle => $LifecycleObj->Name &>
    -+<& /Elements/Submit, Label => loc('Save Changes') &>
    -+
    ++  <div class="form-row">
    ++    <input type="hidden" class="hidden" name="Name" value="<% $LifecycleObj->Name %>" />
    ++    <input type="hidden" class="hidden" name="Type" value="<% $LifecycleObj->Type %>" />
    ++    <div class="col-md-12">
    ++      <& /Elements/Submit, Label => loc('Save Changes') &>
    ++    </div>
    ++      <& /Elements/Lifecycle/Graph, Lifecycle => $LifecycleObj->Name &>
    ++  </div>
     +</form>
     +<%INIT>
     +my ($title, @results);
    @@ -874,12 +876,14 @@
     +$title = loc("Modify lifecycle [_1]", $LifecycleObj->Name);
     +
     +if ($Config) {
    ++    my $LifecycleAttribute = JSON::from_json($LifecycleAttribute);
     +    my ($ok, $msg) = RT::Lifecycle->UpdateLifecycle(
     +        CurrentUser  => $session{CurrentUser},
     +        LifecycleObj => $LifecycleObj,
     +        NewConfig    => JSON::from_json($Config),
    ++        Attribute    => $LifecycleAttribute,
     +    );
    -+    push @results, $msg;
    ++    #push @results, $msg;
     +}
     +
     +# This code does automatic redirection if any updates happen.
    @@ -889,9 +893,10 @@
     +);
     +</%INIT>
     +<%ARGS>
    -+$Name => undef
    -+$Type => undef
    -+$Config => undef
    ++$Name               => undef
    ++$Type               => undef
    ++$Config             => undef
    ++$LifecycleAttribute => undef
     +</%ARGS>
     
     diff --git a/share/html/Admin/Lifecycles/index.html b/share/html/Admin/Lifecycles/index.html
    @@ -951,23 +956,23 @@
     +
     +<h1><&|/l&>Lifecycles</&></h1>
     +
    -+<table cellspacing="0" class="collection collection-as-table">
    -+<tr class="collection-as-table">
    -+  <th class="collection-as-table"><&|/l&>Name</&></th>
    -+  <th class="collection-as-table"><&|/l&>Type</&></th>
    -+  <th class="collection-as-table"><&|/l&>Display</&></th>
    -+</tr>
    ++<div cellspacing="0" class="collection collection-as-table">
    ++  <div class="form-row">
    ++    <div class="col-md-2 collection-as-table"><&|/l&>Name</&></div>
    ++    <div class="col-md-auto collection-as-table"><&|/l&>Type</&></div>
    ++    <div class="col-md-auto collection-as-table"><&|/l&>Display</&></div>
    ++  </div>
     +% my $i = 0;
     +% for my $lifecycle (@lifecycles) {
     +% ++$i;
    -+<tr class="<% $i % 2 ? 'oddline' : 'evenline' %>">
    -+<td class="collection-as-table"><a href="<% RT->Config->Get('WebURL') %>Admin/Lifecycles/Modify.html?Type=<% $lifecycle->Type |u %>&Name=<% $lifecycle->Name |u %>"><% $lifecycle->Name %></a></td>
    -+<td class="collection-as-table"><% loc($lifecycle->Type) %></td>
    ++  <div class="<% $i % 2 ? 'oddline' : 'evenline' %> form-row">
    ++    <div class="collection-as-table col-md-2"><a href="<% RT->Config->Get('WebURL') %>Admin/Lifecycles/Modify.html?Type=<% $lifecycle->Type |u %>&Name=<% $lifecycle->Name |u %>"><% $lifecycle->Name %></a></div>
    ++    <div class="collection-as-table col-md-auto"><% loc($lifecycle->Type) %></div>
     +% my $display = $lifecycle->Type eq 'ticket' ? ($lifecycle->{data}{ticket_display} || 'hidden') : 'hidden';
    -+<td class="collection-as-table"><% loc($display) %></td>
    -+</tr>
    ++    <div class="collection-as-table col-md-auto"><% loc($display) %></div>
    ++  </div>
     +% }
    -+</table>
    ++</div>
     +<%INIT>
     +my @types = List::MoreUtils::uniq(
     +    'ticket',
    @@ -1039,8 +1044,7 @@
     +%# END BPS TAGGED BLOCK }}}
     +<div class="lifecycle-ui" id="lifecycle-<% $id %>">
     +  <div class="row">
    -+    <div class="col-md-7"></div>
    -+    <div class="col-md-5">
    ++    <div class="col-md-12">
     +      <div id="lifeycycle-ui-edit-node" class="lifeycycle-ui-edit-node collapse card card-body">
     +        <input type="hidden" name="id" />
     +        <div class="row">
    @@ -1080,21 +1084,33 @@
     +  <script type="text/javascript">
     +    jQuery(function () {
     +      var container = document.getElementById('lifecycle-<% $id %>'),
    -+        config = <% JSON($config) |n %>,
    -+        name   = <% $Lifecycle | j%>;
    -+
    -+        var editor = new RT.NewEditor( container, config );
    ++        config     = <% JSON($config) |n %>,
    ++        name       = <% $Lifecycle | j%>,
    ++        attribute  = <% $attribute |n %>;
    ++
    ++        var editor = new RT.NewEditor( container, config, attribute );
     +    });
     +  </script>
    -+  <div><p>
    -+    Click in the open space to <strong>add a node</strong>, drag from one node to another while holding control to <strong>add an edge</strong>.
    -+    <br>
    -+    Drag a node to <strong>move the graph layout</strong>.
    -+    <br>
    -+    Click a nodes text to <strong>edit attributes</stong> of the node.
    -+    <br>
    -+    <strong>Click</strong> an edge to interact with it.
    -+  </p></div>
    ++  <div>
    ++    <label class="switch">Disable Simulation
    ++      <input type="checkbox" name="enableSimulation" id="enableSimulation">
    ++    </label>
    ++    <p>
    ++      Click in the open space to <strong>add a node</strong>.
    ++      <br>
    ++      To <strong>delete</strong> a node click on the node to select it and press the 'd' key.
    ++      <br>
    ++      Drag from one node to another while holding <strong>control</strong> to <strong>add an edge</strong>.
    ++      <br>
    ++      Drag a node to <strong>move the graph layout</strong>.
    ++      <br>
    ++      Click a nodes text to <strong>edit attributes</strong> of the node.
    ++      <br>
    ++      <strong>Click an edge</strong> to interact with it.
    ++      <br>
    ++      To disable the simulation and drag nodes to a location without force acting on them click the "Disable simulation" checkbox.
    ++    </p>
    ++  </div>
     +</div>
     +
     +<%INIT>
    @@ -1103,6 +1119,11 @@
     +
     +my $config = RT->Config->Get('Lifecycles')->{$Lifecycle};
     +Abort("Invalid Lifecycle") if !$Lifecycle || !$config;
    ++
    ++my $attributes = RT::Attributes->new( RT->SystemUser );
    ++$attributes->Limit( FIELD => 'Description', VALUE => "LifecycleAttribute-$Lifecycle" );
    ++my $attribute = $attributes->First;
    ++$attribute = $attribute ? JSON($attribute->Content)  : "{}";
     +
     +my $id = $Lifecycle . '-' . int(rand(2**31));
     +</%INIT>
    @@ -1520,22 +1541,39 @@
     @@
     +jQuery( document ).ready(function () {
     +    RT.NewEditor = class LifecycleEditorNew extends LifecycleModel {
    -+        constructor(container, config) {
    ++        constructor(container, config, attribute) {
     +            super("LifecycleModel");
     +
     +            var self         = this;
     +            self.width       = 900;
    -+            self.height      = 500;
    ++            self.height      = 350;
     +            self.node_radius = 35;
    ++            self.attribute   = attribute;
    ++            self.initial     = 1;
    ++
    ++            if ( self.attribute['checked'] ) {
    ++                jQuery('#enableSimulation').prop( "checked", true );
    ++                self.checked = 1;
    ++            }
     +
     +            jQuery("#SaveNode").click(function( event ) {
     +                event.preventDefault();
     +                self.UpdateNode();
     +            });
     +
    -+            self.svg      = d3.select(container).select('svg')
    ++            self.svg = d3.select(container).select('svg')
     +                .attr("preserveAspectRatio", "xMinYMin meet")
    -+                .attr("viewBox", "0 0 900 500");
    ++                .attr("viewBox", "0 0 "+self.width+" "+self.height)
    ++                .attr("border", 1);
    ++
    ++            self.svg.append("rect")
    ++                .attr("x", 0)
    ++                .attr("y", 0)
    ++                .attr("height", self.height)
    ++                .attr("width", self.width)
    ++                .style("stroke", 'black')
    ++                .style("fill", "none")
    ++                .style("stroke-width", 1);
     +
     +            self.config   = config;
     +            self.links    = [];
    @@ -1563,15 +1601,32 @@
     +                    if(link) link.start = true;
     +                    else self.links.push({id: ++self.links_seq, source: source, target: target, start: false, end: true});
     +                });
    ++                if ( self.checked ) {
    ++                    if (self.attribute[source.name][0]) source.x = parseFloat(self.attribute[source.name][0]);
    ++                    if (self.attribute[source.name][1]) source.y = parseFloat(self.attribute[source.name][1]);
    ++                }
     +            });
     +
    -+            self.simulation = d3.forceSimulation()
    -+                .force("link", d3.forceLink().distance(350).strength(0.2))
    -+                .force("charge", d3.forceManyBody().strength(-400))
    -+                .force("center", d3.forceCenter(self.width / 2, self.height / 2))
    -+                .force('collision', d3.forceCollide().radius(function(d) {
    ++            self.simulation = d3.forceSimulation();
    ++            const link_size = self.nodes.length > 10 ? 300 : self.nodes.length * 35;
    ++            if ( self.checked ) {
    ++                self.simulation
    ++                  .force("link", d3.forceLink().distance(link_size < 100 ? 200 : link_size).strength(0))
    ++                  .force("charge", d3.forceManyBody().strength(0))
    ++                  .force("center", d3.forceCenter(self.width / 2, self.height / 2))
    ++                  .force('collision', d3.forceCollide().radius(function(d) {
    ++                    return null;
    ++                  }));
    ++            }
    ++            else {
    ++                self.simulation
    ++                  .force("link", d3.forceLink().distance(link_size < 100 ? 200 : link_size).strength(0.2))
    ++                  .force("charge", d3.forceManyBody().strength(-200))
    ++                  .force("center", d3.forceCenter(self.width / 2, self.height / 2))
    ++                  .force('collision', d3.forceCollide().radius(function(d) {
     +                    return d.radius
     +                  }));
    ++            }
     +
     +            self.SetUp();
     +            self.RenderNode();
    @@ -1581,11 +1636,21 @@
     +                .nodes(self.nodes)
     +                .on("tick", ( t => {
     +                    this.node.attr("transform", (d => {
    ++
     +                        var x = d.x, y = d.y;
     +                        if ( d.x + self.node_radius / 2 > self.width ) x = self.width - self.node_radius;
     +                        if ( d.x - self.node_radius / 2 <= 0 ) x = self.node_radius;
     +                        if ( d.y + self.node_radius / 2 > self.height ) y = self.height - self.node_radius;
     +                        if ( d.y - self.node_radius / 2 <= 0 ) y = self.node_radius;
    ++
    ++                        if ( self.checked ) {
    ++                            d.fx = x;
    ++                            d.fy = y;
    ++                        }
    ++                        else {
    ++                            d.fx = null;
    ++                            d.fy = null;
    ++                        }
     +
     +                        return "translate(" + x + "," + y + ")";
     +                    }));
    @@ -1629,6 +1694,18 @@
     +            var field = jQuery('<input type="hidden" name="Config">');
     +            field.val(JSON.stringify(self.config));
     +            form.append(field);
    ++
    ++            var pos = {};
    ++            self.nodes.forEach( d => {
    ++                pos[d.name] = [d.x, d.y];
    ++            });
    ++
    ++            var attribute = jQuery('<input name="LifecycleAttribute" type="hidden">');
    ++            attribute.val(JSON.stringify(pos));
    ++            form.append(attribute);
    ++
    ++            self.initial = 0;
    ++            self.ExportAsConfiguration();
     +        }
     +
     +        SetUp() {
    @@ -1706,6 +1783,10 @@
     +                    });
     +                }
     +            })
    ++
    ++            jQuery('#enableSimulation').click(function(){
    ++                self.ToggleSimulation();
    ++            });
     +        }
     +
     +        RenderNode() {
    @@ -1719,13 +1800,14 @@
     +
     +            // Add new nodes and draw them
     +            var nodeEnter = self.node.enter().append("g")
    -+                .attr("class", "node")
    ++                .attr("class", "node");
     +
     +            nodeEnter.append("circle");
     +            nodeEnter.append("text");
     +            nodeEnter.append("title");
     +
    -+            self.node = nodeEnter.merge(self.node);
    ++            self.node = nodeEnter.merge(self.node)
    ++                .attr("id", d => { d.id });
     +
     +            self.node.call(d3.drag()
     +                .on("start", (d => {
    @@ -1737,7 +1819,9 @@
     +                }))
     +                .on("end", (d => {
     +                    if (!d3.event.active) this.simulation.alphaTarget(0);
    -+                    d.fx = null, d.fy = null;
    ++                    if ( !self.checked ) {
    ++                        d.fx = null, d.fy = null;
    ++                    }
     +                })));
     +
     +            // Add our circle to our new node
    @@ -1825,12 +1909,24 @@
     +                    jQuery(item).val(element[item.name]);
     +                    // Can we make this check for the select bootstrap class instead of hard coding the known fields?
     +                    if ( item.name === 'type' ) {
    -+                        jQuery(".bootstrap-select .filter-option").text(element[item.name])
    ++                        var type = jQuery(".bootstrap-select .filter-option");
    ++                        if ( type ) {
    ++                            type.text(element[item.name]);
    ++                        }
     +                    }
     +                }
     +                self.editing_node = element;
     +            }
     +            else {
    ++                var name = document.getElementsByName('name')[0].value;
    ++                if ( ( this.nodes.findIndex(x => x.name == name ) > 0 && this.nodes.findIndex(x => x.name == name ) <= 1 ) || name === '' ) {
    ++                    // FIXME
    ++                    // var form  = jQuery('#lifeycycle-ui-edit-node');
    ++                    // var field = jQuery('<div class="alert alert-warning removing">Name invalid</div>');
    ++                    // form.append(field);
    ++                    return;
    ++                }
    ++
     +                var values = {};
     +                for (let item of list) {
     +                    if ( item.name === 'id' ) {
    @@ -1889,14 +1985,21 @@
     +        Refresh() {
     +            var self = this;
     +
    ++            const link_size = self.nodes.length > 10 ? 300 : self.nodes.length * 35;
    ++            self.simulation
    ++                .force("link", d3.forceLink().distance(link_size < 100 ? 200 : link_size).strength(0.2))
    ++
     +            self.simulation
     +                .nodes(self.nodes)
     +                .force("link")
    -+                    .links(self.links)
    -+                    .id(d => d.id);
    ++                .links(self.links)
    ++                        .id(d => d.id);
     +
     +            self.RenderLink();
     +            self.RenderNode();
    ++
    ++            jQuery('.removing').remove();
    ++
     +            // This is our "cooling" factor
     +            self.simulation.alpha(0.05).restart();
     +        }
    @@ -1912,6 +2015,7 @@
     +        Deselect() {
     +            if ( jQuery("#lifeycycle-ui-edit-node").is(':visible') ) {
     +                jQuery("#lifeycycle-ui-edit-node").toggle();
    ++                jQuery('.removing').remove();
     +            }
     +
     +            this.editing_node = null;
    @@ -1967,6 +2071,36 @@
     +            self.mousedown_link  = null;
     +            self.mousedown_node  = null;
     +            self.mouseup_node    = null;
    ++        }
    ++
    ++        ToggleSimulation(){
    ++            var self = this;
    ++            self.checked = jQuery('#enableSimulation').is(":checked");
    ++
    ++            const link_size = self.nodes.length > 10 ? 300 : self.nodes.length * 35;
    ++            if ( self.checked ) {
    ++                self.simulation
    ++                  .force("link", d3.forceLink().distance(link_size < 100 ? 200 : link_size).strength(0))
    ++                  .force("charge", d3.forceManyBody().strength(0))
    ++                  .force("center", d3.forceCenter(self.width / 2, self.height / 2))
    ++                  .force('collision', d3.forceCollide().radius(function(d) {
    ++                    return null;
    ++                  }));
    ++            }
    ++            else {
    ++                self.nodes.forEach(function(d) {
    ++                    d.fx = null, d.fy = null;
    ++                });
    ++
    ++                self.simulation
    ++                  .force("link", d3.forceLink().distance(link_size < 100 ? 200 : link_size).strength(0.2))
    ++                  .force("charge", d3.forceManyBody().strength(-200))
    ++                  .force("center", d3.forceCenter(self.width / 2, self.height / 2))
    ++                  .force('collision', d3.forceCollide().radius(function(d) {
    ++                    return d.radius
    ++                  }));
    ++            }
    ++            self.ExportAsConfiguration();
     +        }
     +    }
     +});
    @@ -2160,5 +2294,20 @@
     +
     +        var field = jQuery('input[name="Config"]');
     +        field.val(JSON.stringify(self.config));
    ++
    ++        var pos = {};
    ++        if ( jQuery('#enableSimulation').is(":checked") ) {
    ++            pos["checked"] = 1;
    ++            self.nodes.forEach( d => {
    ++                pos[d.name] = [d.fx, d.fy];
    ++            });
    ++        }
    ++        else {
    ++            pos = JSON.parse(jQuery('input[name="LifecycleAttribute"]').val())
    ++            pos["checked"] = 0;
    ++            console.log(pos);
    ++        }
    ++        var attribute = jQuery('input[name="LifecycleAttribute"]');
    ++        attribute.val(JSON.stringify(pos));
     +    };
     +}



More information about the rt-commit mailing list