From 43bbaa7c438190e9005a47b265483e1df597c282 Mon Sep 17 00:00:00 2001 From: Mark Casias Date: Tue, 28 Jul 2015 16:18:41 -0600 Subject: [PATCH 1/6] Added JS from 7.x branch to 8.x --- modules/rules_ui/js/rules.autocomplete.js | 199 ++++++++++++++++++++++ modules/rules_ui/js/rules.debug.js | 68 ++++++++ 2 files changed, 267 insertions(+) create mode 100644 modules/rules_ui/js/rules.autocomplete.js create mode 100644 modules/rules_ui/js/rules.debug.js diff --git a/modules/rules_ui/js/rules.autocomplete.js b/modules/rules_ui/js/rules.autocomplete.js new file mode 100644 index 00000000..ee6323b7 --- /dev/null +++ b/modules/rules_ui/js/rules.autocomplete.js @@ -0,0 +1,199 @@ + +// Registers the rules namespace. +Drupal.rules = Drupal.rules || {}; + +(function($) { + Drupal.behaviors.rules_autocomplete = { + attach: function(context) { + var autocomplete_settings = Drupal.settings.rules_autocomplete; + + $('input.rules-autocomplete').once(function() { + var input = this; + new Drupal.rules.autocomplete(input, autocomplete_settings[$(input).attr('id')]); + }); + } + }; + + /** + * Rules autocomplete object. + */ + Drupal.rules.autocomplete = function(input, settings) { + this.id = settings.inputId; + this.uri = settings.source; + this.jqObject = $('#' + this.id); + this.cache = []; + this.jqObject.addClass('ui-corner-left'); + + this.opendByFocus = false; + this.focusOpens = true; + this.groupSelected = false; + + this.button = $(' '); + this.button.attr( { + 'tabIndex': -1, + 'title': 'Show all items' + }); + this.button.insertAfter(this.jqObject); + + this.button.button( { + icons: { + primary: 'ui-icon-triangle-1-s' + }, + text: false + }); + + // Don't round the left corners. + this.button.removeClass('ui-corner-all'); + this.button.addClass('ui-corner-right ui-button-icon rules-autocomplete-button'); + + this.jqObject.autocomplete(); + this.jqObject.autocomplete("option", "minLength", 0); + // Add a custom class, so we can style the autocomplete box without + // interfering with other jquery autocomplete widgets. + this.jqObject.autocomplete("widget").addClass('rules-autocomplete'); + + // Save the current rules_autocomplete object, so it can be used in + // handlers. + var instance = this; + + // Event handlers + this.jqObject.focus(function() { + if (instance.focusOpens) { + instance.toggle(); + instance.opendByFocus = true; + } + else { + instance.focusOpens = true; + } + }); + + // Needed when the window is closed but the textfield has the focus. + this.jqObject.click(function() { + // Since the focus event happens earlier then the focus event, we need to + // check here, if the window should be opened. + if (!instance.opendByFocus) { + instance.toggle(); + } + else { + instance.opendByFocus = false; + } + }); + + this.jqObject.bind("autocompleteselect", function(event, ui) { + // If a group was selected then set the groupSelected to true for the + // overridden close function from jquery autocomplete. + if (ui.item.value.substring(ui.item.value.length - 1, ui.item.value.length) == ":") { + instance.groupSelected = true; + } + instance.focusOpens = false; + instance.opendByFocus = false; + }); + + this.jqObject.autocomplete("option", "source", function(request, response) { + if (request.term in instance.cache) { + response(instance.cache[request.term]); + return; + } + $.ajax( { + url: instance.uri + '/' + request.term, + dataType: "json", + success: function(data) { + instance.success(data, request, response); + } + }); + }); + + // Since jquery autocomplete by default strips html text by using .text() + // we need our own _renderItem function to display html content. + this.jqObject.data("autocomplete")._renderItem = function(ul, item) { + return $("
  • ").data("item.autocomplete", item).append("" + item.label + "").appendTo(ul); + }; + + // Override close function + this.jqObject.data("autocomplete").close = function (event) { + var value = this.element.val(); + // If the selector is not a group, then trigger the close event an and + // hide the menu. + if (value === undefined || instance.groupSelected === false) { + clearTimeout(this.closing); + if (this.menu.element.is(":visible")) { + this._trigger("close", event); + this.menu.element.hide(); + this.menu.deactivate(); + } + } + else { + // Else keep all open and trigger a search for the group. + instance.jqObject.autocomplete("search", instance.jqObject.val()); + // After the suggestion box was opened again, we want to be able to + // close it. + instance.groupSelected = false; + } + }; + + this.button.click(function() { + instance.toggle(); + }); + + }; + + /** + * Success function for Rules autocomplete object. + */ + Drupal.rules.autocomplete.prototype.success = function(data, request, response) { + var list = []; + jQuery.each(data, function(index, value) { + list.push( { + label: value, + value: index + }); + }); + + this.cache[request.term] = list; + response(list); + }; + + /** + * Open the autocomplete window. + * @param searchFor + * The term for will be searched for. If undefined then the entered input + * text will be used. + */ + Drupal.rules.autocomplete.prototype.open = function(searchFor) { + // If searchFor is undefined, we want to search for the passed argument. + if (searchFor == undefined) { + searchFor = this.jqObject.val(); + } + this.jqObject.autocomplete("search", searchFor); + this.button.addClass("ui-state-focus"); + }; + + /** + * Close the autocomplete window. + */ + Drupal.rules.autocomplete.prototype.close = function() { + this.jqObject.autocomplete("close"); + this.button.removeClass("ui-state-focus"); + }; + + /** + * Toogle the autcomplete window. + */ + Drupal.rules.autocomplete.prototype.toggle = function() { + if (this.jqObject.autocomplete("widget").is(":visible")) { + this.close(); + this.focusOpens = true; + } + else { + var groups = this.jqObject.val().split(":"); + var selector = ""; + for (var i=0; i Date: Tue, 28 Jul 2015 16:19:04 -0600 Subject: [PATCH 2/6] Added CSS from 7.x to 8.x --- modules/rules_ui/css/rules.ui.css | 196 ++++++++++++++++++++++++ modules/rules_ui/css/rules.ui.seven.css | 95 ++++++++++++ 2 files changed, 291 insertions(+) create mode 100644 modules/rules_ui/css/rules.ui.css create mode 100644 modules/rules_ui/css/rules.ui.seven.css diff --git a/modules/rules_ui/css/rules.ui.css b/modules/rules_ui/css/rules.ui.css new file mode 100644 index 00000000..c0bc7c9d --- /dev/null +++ b/modules/rules_ui/css/rules.ui.css @@ -0,0 +1,196 @@ +@CHARSET "UTF-8"; + +.rules-show-js, html.js .rules-hide-js { + display: none; +} + +.rules-hide-js, html.js .rules-show-js { + display: block; +} + +.rules-elements-table ul.action-links { + margin: 0; + padding: 0; +} + +.rules-elements-table ul.rules-operations li { + list-style: none; + float: left; +} + +.rules-elements-table ul.rules-operations a { + background: none; + padding-left: 0; +} + +table tr.rules-elements-add { + background-color: #e5eff4; +} + +.rules-elements-table ul.rules-operations-add a { + line-height: 1em; +} + + +tr.rules-elements-add td { + padding-top: 2px; + padding-bottom: 2px; +} + +ul.rules-operations-add li { + float: left; + list-style-position: inside; +} + +.rules-elements-table { + margin-bottom: 3em; +} +/* We cannot set a positive margin-top for rules tables as the table drag link + should be positioned directly on top of the table. Thus we use a large bottom + margin and fix the upper most margin: */ +#rules-form-wrapper:first-child { + margin-top: 1.5em; +} + +/* Fix table drag weights to don't take extra space */ +.rules-elements-table .tabledrag-toggle-weight-wrapper { + position: absolute; + right: 0; +} + +.rules-elements-table caption, .rules-overview-table caption { + font-size: 110%; + font-weight: bold; + padding-bottom: 0.5em; + text-align: left; +} + +.rules-overview-table { + margin: 1em 0; +} + +.rules-content-group-integrity-error { + color: #df0101; +} + +.rules-debug-log { + font: 81.3% "Lucida Grande","Lucida Sans Unicode",sans-serif; + background-color: #eeeeee; + border: 1px solid #cccccc; + color: #333333; + padding: 5px; + margin: 1.5em 0; +} + +.rules-debug-collapsible-link { + position: relative; + cursor: pointer; + + /* The span element with the icon which opens the log, has a whitepsace. + Since we don't want the user to mark this white space, we prevent this + using the this code.*/ + -moz-user-select: -moz-none; + -khtml-user-select: none; + -webkit-user-select: none; + -o-user-select: none; + user-select: none; +} + +.rules-debug-log-head { + font-weight: bold; +} + +div.rules-debug-log-head { + margin: 0.5em 0; +} + +.rules-debug-icon-open { + position: relative; + float: left; +} + +.rules-debug-open-all { + position: relative; + float: right; +} + +.rules-debug-log ul { + padding-left: 2em; +} + +.rules-debug-log .rules-debug-warn { + color: #df0101; +} + +.rules-debug-log .rules-debug-error { + font-weight: bold; + color: #df0101; +} + +#rules-filter-form { + margin-bottom: 1.5em; +} + +.rules-parameter-label { + font-style: italic; +} + +#rules-plugin-add-help { + margin-bottom: 1em; +} + +.rules-element-content { + float: left; +} + +form input.rules-switch-button { + -moz-border-radius: 5px 5px 5px 5px; + cursor: pointer; + font-size: 0.8em; + font-weight: normal; + margin-bottom: 1em; + padding: 2px; + text-align: center; +} + +.rules-form-heading { + margin-top: 3em; +} + +.rules-autocomplete-button { + top: 3px; + height: 22px; +} + +ul.rules-autocomplete { + max-height: 23em; + overflow-y: auto; +} + +ul.rules-autocomplete div { + padding-left: 5px; +} + +ul.rules-autocomplete a.ui-corner-all { + padding: 0; +} + +ul.rules-autocomplete .rules-dsac-group { + background-color: #eee; +} + +ul.rules-autocomplete .ui-corner-all { + -moz-border-radius: 0; +} + +/** + * Do not display the hide/show descriptions link above the permissions matrix. + */ +#rules-form-wrapper #edit-settings-access-permissions .compact-link { + display: none; +} + +/* IE 6 hack for max-height. */ +* html ul.rule-autocomplete{ + height: 23em; +} diff --git a/modules/rules_ui/css/rules.ui.seven.css b/modules/rules_ui/css/rules.ui.seven.css new file mode 100644 index 00000000..e019d007 --- /dev/null +++ b/modules/rules_ui/css/rules.ui.seven.css @@ -0,0 +1,95 @@ +/** + * JQuery UI style sheet fix for the seven theme. + */ + +.ui-button { + border: 1px solid #cccccc; + background: #e6e6e6; +} + +.ui-state-hover, +.ui-state-focus { + border: 1px solid #bbbbbb; +} + +.ui-button.ui-state-active { + border: 1px solid #777777; + font-weight: bold; +} + +/** + * Corner radius + */ +.ui-corner-tl { + -moz-border-radius-topleft: 4px; + -webkit-border-top-left-radius: 4px; + border-top-left-radius: 4px; +} + +.ui-corner-tr { + -moz-border-radius-topright: 4px; + -webkit-border-top-right-radius: 4px; + border-top-right-radius: 4px; +} + +.ui-corner-bl { + -moz-border-radius-bottomleft: 4px; + -webkit-border-bottom-left-radius: 4px; + border-bottom-left-radius: 4px; +} + +.ui-corner-br { + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.ui-corner-top { + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +.ui-corner-bottom { + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; +} + +.ui-corner-right { + -moz-border-radius-bottomright: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; +} + +.ui-corner-left { + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-topleft: 4px; + -webkit-border-bottom-left-radius: 4px; + -webkit-border-top-left-radius: 4px; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} + +.ui-corner-all { + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; +} + +/** + * Fix the position of the core-autocomplete popup when shown in the settings + * fieldset. + */ +.form-item-settings-tags { + position: relative; +} From d6ba773ba655bbfd0046e98b23c52ed64f011f60 Mon Sep 17 00:00:00 2001 From: Mark Casias Date: Fri, 7 Aug 2015 19:07:10 -0600 Subject: [PATCH 3/6] Pushing default settings into a fieldset --- src/Entity/RulesComponentFormBase.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Entity/RulesComponentFormBase.php b/src/Entity/RulesComponentFormBase.php index 51cbabdf..010fe0ee 100644 --- a/src/Entity/RulesComponentFormBase.php +++ b/src/Entity/RulesComponentFormBase.php @@ -19,27 +19,33 @@ abstract class RulesComponentFormBase extends EntityForm { * {@inheritdoc} */ public function form(array $form, FormStateInterface $form_state) { - $form['label'] = [ + $form['settings'] = array( + '#type' => 'fieldset', + '#title' => $this->t('Settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['settings']['label'] = [ '#type' => 'textfield', '#title' => $this->t('Label'), '#default_value' => $this->entity->label(), '#required' => TRUE, ]; - $form['id'] = [ + $form['settings']['id'] = [ '#type' => 'machine_name', '#description' => t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'), '#disabled' => !$this->entity->isNew(), '#default_value' => $this->entity->id(), '#machine_name' => [ 'exists' => [$this, 'exists'], - 'replace_pattern' =>'([^a-z0-9_]+)|(^custom$)', + 'replace_pattern' => '([^a-z0-9_]+)|(^custom$)', 'error' => $this->t('The machine-readable name must be unique, and can only contain lowercase letters, numbers, and underscores. Additionally, it can not be the reserved word "custom".'), ], ]; // @todo enter a real tag field here. - $form['tag'] = [ + $form['settings']['tag'] = [ '#type' => 'textfield', '#title' => $this->t('Tag'), '#default_value' => $this->entity->getTag(), @@ -47,7 +53,7 @@ public function form(array $form, FormStateInterface $form_state) { '#required' => TRUE, ]; - $form['description'] = [ + $form['settings']['description'] = [ '#type' => 'textarea', '#default_value' => $this->entity->getDescription(), '#description' => t('Enter a description for this component.'), From c01f6a0b300e5732eaeb716970e45f0a2353c278 Mon Sep 17 00:00:00 2001 From: Mark Casias Date: Fri, 7 Aug 2015 19:07:38 -0600 Subject: [PATCH 4/6] Adding base fieldsets for different components --- src/Entity/ReactionRuleEditForm.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Entity/ReactionRuleEditForm.php b/src/Entity/ReactionRuleEditForm.php index dc843eb2..b2d042b3 100644 --- a/src/Entity/ReactionRuleEditForm.php +++ b/src/Entity/ReactionRuleEditForm.php @@ -23,6 +23,25 @@ protected function actions(array $form, FormStateInterface $form_state) { return $actions; } + /** + * {@inheritdoc} + */ + public function form(array $form, FormStateInterface $form_state) { + $form['rule_events'] = array( + '#type' => 'fieldset', + '#title' => $this->t('Events'), + ); + $form['rule_conditions'] = array( + '#type' => 'fieldset', + '#title' => $this->t('Conditions'), + ); + $form['rule_actions'] = array( + '#type' => 'fieldset', + '#title' => $this->t('Actions'), + ); + return parent::form($form, $form_state); + } + /** * {@inheritdoc} */ From 73cf2b92c641e8f6240bd8528eb2f4be63887363 Mon Sep 17 00:00:00 2001 From: Mark Casias Date: Fri, 7 Aug 2015 19:23:14 -0600 Subject: [PATCH 5/6] creating library yml for attaching to form --- modules/rules_ui/rules_ui.libraries.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 modules/rules_ui/rules_ui.libraries.yml diff --git a/modules/rules_ui/rules_ui.libraries.yml b/modules/rules_ui/rules_ui.libraries.yml new file mode 100644 index 00000000..7c476d73 --- /dev/null +++ b/modules/rules_ui/rules_ui.libraries.yml @@ -0,0 +1,9 @@ +rules_ui: + version: 1.x + css: + theme: + css/rules.ui.css: {} + js: + js/rules.autocomplete.js: {} + dependencies: + - core/jquery From f7003cea1bdc6726167d9f57bdf2fa35bb585ac8 Mon Sep 17 00:00:00 2001 From: Mark Casias Date: Fri, 7 Aug 2015 19:23:25 -0600 Subject: [PATCH 6/6] Attaching to edit form. --- src/Entity/ReactionRuleEditForm.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Entity/ReactionRuleEditForm.php b/src/Entity/ReactionRuleEditForm.php index b2d042b3..4335cb6b 100644 --- a/src/Entity/ReactionRuleEditForm.php +++ b/src/Entity/ReactionRuleEditForm.php @@ -39,6 +39,9 @@ public function form(array $form, FormStateInterface $form_state) { '#type' => 'fieldset', '#title' => $this->t('Actions'), ); + $form['#attached']['library'] = array( + 'rules_ui/rules_ui', + ); return parent::form($form, $form_state); }