[Initial Release] Rule Machine Manager (New Rule Machine Interface)

Thanks, I'm using the Dark Reader Chrome extension.

Thinking about it again, if you want to move a rule out of a user-created container, then I guess you still need to displayed. All good.

Ah, I see now, there is a built-in method you can call to get the rules list.
RMUtils.getRuleList("5.0")

That was something I noticed earlier but forgot to mention... I think on one of my dev hubs I had the legacy version of RM running, and I'm pretty sure those rules didn't show up. So you may want to mention that or, if possible, find a way to retrieve them as well.

The reason @rlithgow1 was mentioning about UI changes is because it may have messed this up if you were trying to use the method I posted about earlier, where I was calling the Apps page in my driver and using regex in to parse the HTML and find Apps installed on the hub. I haven't looked at my code in ages, so not sure if it still works. Would be great if there was a similar method to call to retrieve apps more generally.

2 Likes

I copied code and got an error
unexpected token: g @ line 164, column 34.

jQuery( document ).ready( function( $) {

// Initial rulelist sortable
initialize_sort();

// Set initial input on page load
rebuildArray();

// Edit title button
$( document ).on( 'click', 'i.edit', function() {
	
	// Get original value
	var orig_value = $( this ).siblings( 'span.group_name' ).text();
	
	// Create submit/cancel buttons and replace html
	var edit_input = '<input type="text" class="edit_title_input" value="' + orig_value + '" /> <span class="button submit_edit">Submit</span> <span class="button cancel_edit">Cancel</span>';
	$( this ).siblings( 'span.group_name' ).html( edit_input );
});

// Cancel edit title button
$( document ).on( 'click', 'span.cancel_edit', function() {
	
	// Get original value
	var orig_value = $( this ).siblings( 'input.edit_title_input' ).val();
	
	// Replace title with original value
	$( this ).parent().html( orig_value );
	rebuildArray();
});

// Submit edit title button
$( document ).on( 'click', 'span.submit_edit', function() {
	
	// Get new value
	var new_value = $( this ).siblings( 'input.edit_title_input' ).val();
	
	// Replace title with new value
	$( this ).parent().html( new_value );
	
	// Rebuild array
	rebuildArray();
});

// Create section button
$( "span#create_group_button" ).click( function() {

	// Get name from input
	var name = $( 'input#new_group_name' ).val();

	// If no name, alert and bail
	if( name == '' ) {

		alert( "Please enter a valid Group Name.");
		return false;
	}
	
	// Create html for new container
	var html = '';
	html += '<div id="" class="rule_container">';
		html += '<h4>';
			html += '<span class="group_name">' + name + '</span>';
			html += '<span class="group_rule_count"><em>(0 items)</em></span>';
			html += '<i class="material-icons delete_group" title="Delete Group">delete</i>';
			html += '<i class="material-icons expand" title="Toggle Open/Close">file_upload</i>';
			html += '<i class="material-icons drag_handle" title="Drag/Sort">reorder</i>'
			html += '<i class="material-icons edit" title="Edit Title">edit</i>'
		html += '</h4>';
		html += '<ul class="rulelist"></ul>';
	html += '</div>';

	// Append container to page
	$( 'div#rules_container' ).append( html );
	
	// Clear input field
	$( 'input#new_group_name' ).val( '' );
	
	// Rebuild array
	rebuildArray();
	
	// Initialize sort
	initialize_sort();
});

// Delete section button
$( document ).on( 'click', 'i.delete_group', function() {
	
	var this_delete = $( this );
	
	// Confirm deletion
	if( confirm( "Permenantly delete the group?\nAny remaining rules in this group will be moved to the Original Rules group." ) == true ) {
		
		// Check if any rules exist in container
		var check_rules = $( this_delete ).parent().siblings( 'ul' ).children();
		
		// If rules are found
		if( check_rules.length !== 0 ) {
			
			// Copy rules and append to original rules container
			var copy_html = $( this_delete ).parent().siblings( 'ul' ).html();
			$( 'div#original-rules' ).find( 'ul.rulelist' ).append( copy_html );
	
			// Remove container
			$( this_delete ).parent().parent().remove();
			
			// Rebuild array
			rebuildArray();
		}
	}
});

// Toggle open/close
$( document ).on( 'click', 'i.expand', function() {
	
	// Switch material icon from open/close
	if( $( this ).text() == 'file_upload' ) {
		$( this ).text( 'file_download' );
	}
	else if( $( this ).text() == 'file_download' ) {
		$( this ).text( 'file_upload' );
	}
	
	// Toggle list
	$( this ).parent().siblings( 'ul' ).toggle();
	
	// Rebuild array
	rebuildArray();
});

});

// Build new user array
function rebuildArray() {

// Define base array
var rb_array = [];

// Loop each container
$( 'div.rule_container' ).each( function() {
	
	// Create container array and populate
	var title = $( this ).children( 'h4' ).children( 'span.group_name' ).text();
	var this_array = {};
	this_array.name = title;
	this_array.slug = string_to_slug( title );
	this_array.visible = $( this ).children( 'ul' ).is( ':visible' );
	this_array.rules = [];
	$( this ).children( 'ul' ).children( 'li' ).each( function(i, v) { this_array.rules.push( v.id ); });
	
	// Count rules in this container and display on page
	var count = this_array.rules.length;
	var items = count == 1 ? 'item' : 'items';
	$( this ).children( 'h4' ).children( 'span.group_rule_count' ).html( '<em>(' + count + ' ' + items + ')</em>' );
	
	// Push this container to base array
	rb_array.push( this_array );
});

// Populate hidden input with new user array
$( 'input#userArray' ).val( JSON.stringify( rb_array ) );

}

function string_to_slug( str ) {

// Trim string and cast to lowercase
str = str.replace(/^\s+|\s+$/g, '');
str = str.toLowerCase();

// Remove accents, swap ñ for n, etc
var from = "à áäâèéëêìíïîòóöôùúüûñç·/_,:;";
var to   = "aaaaeeeeiiiioooouuuunc------";
for (var i=0, l=from.length ; i<l ; i++) {
    str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
}

// Remove invalid characters; collapse whitespace and replace with -; collapse dashes
str = str.replace(/[^a-z0-9 -]/g, '').replace(/\s+/g, '-').replace(/-+/g, '-');

return str;

}

function initialize_sort() {

// Sort main containers
$( "div#rules_container" ).sortable({
	handle: '.drag_handle',
	containment: "parent",
	stop: function() {
		
		rebuildArray();
	}
});

// Sort container rule sets
$( ".rulelist" ).sortable({
	connectWith: '.rulelist',
	stop: function() {
		
		rebuildArray();
	}
});

}

I think you are attempting to install the incorrect file. It looks like you are trying to install the javascript file into your hubitat app page. That is incorrect. You want to install the "rule_machine_manager.groovy" file into the hubitat app manager.

Here is the correct link again:
[rule_machine_manager.groovy]

NOTE This post is outdated. Please install via HPM or see first post for local install instructions.

2 Likes

You are correct, Thanks for the help!!!

1 Like

Yes, I did notice when I used that function, that it noted there was another legacy version. Without having some of the legacy features; I'm not sure I can support legacy. I may just have to note RM5.0 only moving forward.

I'm still learning my way with groovy. I'm great at js and php. Groovy does a lot of things differently; syntactically. Don't even get me started on arrays and array iterations. I'm getting there, though.

I will definitely take a look at your "starter projects?" later tonight when I get back home.

1 Like

Can you provide me with a use-case here? I'm thinking about implementing; but not quite sure what I'm going for. Is it just to more easily find a rule that might be use in multiple places? Like, at 10am open the garage door and turn on living room light? That should appear in Garage and Living Room?

1 Like

Yes, that's what I had in mind. So that if you want to group together automations that impact either room (or whatever the trouping represents) you can see a complete list for each room. I talk a little bit about it towards the end of this post.

1 Like

Thanks very much for this - really cool stuff.

Sorry if I missed discussion of this, but a search on "multi" and "select" didn't find it.

Will it be possible to enable multi-select, so we can select multipe rules and then move them together into a group? Or is this already supported and I'm not seeing how to do it?

2 Likes

I can confirm JS files work when stored in file manager. I have one there I use with an app of mine.

1 Like

Is there a way to add the other type rules to a folder? Like, simple automation, motion, basic, etc.

I suggested that up above also, it only works for RM right now but it is something he is taking into consideration.

Thanks, very cool app

Ugh.. I can't believe I didn't think of this during development. Yes, I'll absolutely look into adding multi-select. Thank you.

Thank you. I was fairly certain it would work. I'm not sure how to use HPM to do the copy of the file into the hubitat.. but I'll start looking into that feature.

I am currently looking at this option. I will report back soon.

3 Likes

Okay.. please help me identify the other areas that use "rules" which we would like to see pulled into this app. I'm going to start a list here. Please let me know if I missed something here, or if one of these is not correct.

  • Basic Button Controllers
  • Basic Rules
  • Button Controllers
  • Dashboards (?? Maybe?)
  • Motion/Mode Lighting Apps
  • Room Lighting
  • Simple Automation Rules
2 Likes

BUG: Noted for posterity (will fix when it's not so late here)

Empty containers are not being removed correctly after deletion. In the meantime, to delete a custom created container, move at least one item into the container to be deleted, then delete the container. The container will be removed successfully, and the rule will be returned to the "Original Rules" container.

3 Likes

7 posts were split to a new topic: Beta or not

Add bold text and color to folder titles.

3 Likes

Well then, lemme bring it back full circle!

I love the idea of customizing the container headers. I'm working on an interface that will allow a few variations on font and color.

I definitely want to spend a little time on mobile UI/UX.

Bringing in other rules is proving to be somewhat of a challenge. I haven't found any magic utility like "RMUtils()" for the other sections. But I'm still digging...

4 Likes

It seems when you create a new rule group it stacks one below the other. Example

1st rule created
2nd rule created
3rd rule created

Every time you create a new group you have to drag the rule passed the groups already made.

Can you make the new group appear on top?

3rd rule created
2nd rule created
1st rule created

Is this possible?

1 Like