mushy 0.0.5 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 971693353748e8d21c56dfa911cf669b79a10fce38530eaeb9c8ab019c69be73
4
- data.tar.gz: 58ef99b38f1ebc13fbd68bca3e6597b43ba4310313e780ab38c55e14dcc31b07
3
+ metadata.gz: 2eaed069f8d37db0a6d58fea9c994e4a5135f43a18a7e7ad8421a601983bb954
4
+ data.tar.gz: 3224715b652898edaac99ad89a8378ccc4d2aa4ba21b891ca33fec0b99252a85
5
5
  SHA512:
6
- metadata.gz: f124d798c6d44e1ecefc2b5b44726c20f7c5e07ed25182776cf2db69e230ef646d84d45627f5d645ff04be725c7db891bf597c4317bd42f9372a070b425cc72c
7
- data.tar.gz: f7a5875f509dd43c1543c89636a9e435ff0cabec094fe109113f173fb26e6eef6bd0a0f0634dc35f1ee78f9c71f6e7e6fd166515f222383f3fcef8d4be4f4deb
6
+ metadata.gz: df28cc21a604e023284ad3f88b2cd11a3ab4261c3cd9747a2033d07528203262de29daa2d12f82e404eb91109b79ee9a5e5a5bf71396c360e26ff270d08a2449
7
+ data.tar.gz: 05410eb4c9fee4afd4aa31397409b6c794bc152257cf599aa4fb1502cb7009c518b9fac2eb76b3f78ca1e58e2a31e28e6dcd6c5266febb8bddd7ea7fbe7fdea1
data/bin/mushy CHANGED
@@ -3,18 +3,20 @@
3
3
  require 'thor'
4
4
  require 'mushy'
5
5
 
6
- class RailsCLI < Thor
6
+ class MushyCLI < Thor
7
+
8
+ argument :file, optional: true, type: :string
9
+ argument :values, optional: true, type: :hash
7
10
 
8
11
  desc "start FILE", "Run this workflow file."
9
- def start file
10
- content = File.open(file).read
11
- puts content
12
+ def start
13
+ Mushy::Builder::Api.start file, values
12
14
  end
13
15
 
14
16
  desc "build FILE", 'Build a flow.'
15
- def build file
17
+ def build
16
18
 
17
- RailsCLI.set_special( { method: 'build', file: file } )
19
+ MushyCLI.set_special( { method: 'build', file: file } )
18
20
 
19
21
  end
20
22
 
@@ -28,14 +30,14 @@ class RailsCLI < Thor
28
30
 
29
31
  end
30
32
 
31
- RailsCLI.start(ARGV)
33
+ MushyCLI.start(ARGV)
32
34
 
33
- exit unless RailsCLI.get_special
35
+ exit unless MushyCLI.get_special
34
36
 
35
37
  require 'sinatra'
36
38
  enable :run
37
39
 
38
- the_file = RailsCLI.get_special[:file]
40
+ the_file = MushyCLI.get_special[:file]
39
41
 
40
42
  get '/' do
41
43
  Mushy::Builder::Index.file
@@ -28,6 +28,15 @@ module Mushy
28
28
 
29
29
  end
30
30
 
31
+ def self.start file, event
32
+ file = "#{file}.json" unless file.downcase.end_with?('.json')
33
+ flow = File.open(file).read
34
+ flow = Mushy::Flow.parse flow
35
+ flux = flow.fluxs.select { |x| x.type == 'Cli' }.first
36
+
37
+ Mushy::Runner.new.start event, flux, flow
38
+ end
39
+
31
40
  def self.get_flow file
32
41
  puts "trying to get: #{file}"
33
42
  file = "#{file}.json" unless file.downcase.end_with?('.json')
@@ -40,14 +49,14 @@ module Mushy
40
49
  {
41
50
  fluxs: Mushy::Flux.all.select { |x| x.respond_to? :details }.map do |flux|
42
51
  details = flux.details
43
- details[:config][:incoming_split] = { type: 'text', description: 'Split an incoming event into multiple events by this key, an each event will be processed independently.', default: '' }
44
- details[:config][:outgoing_split] = { type: 'text', description: 'Split an outgoing event into multiple events by this key.', default: '' }
45
- details[:config][:merge] = { type: 'text', description: 'A comma-delimited list of fields from the event to carry through. Use * to merge all fields.', default: '' }
46
- details[:config][:group] = { type: 'text', description: 'Group events by a field, which is stored in a key. The format is group_by|group_key.', default: '' }
47
- details[:config][:limit] = { type: 'integer', description: 'Limit the number of events to this number.', default: '' }
48
- details[:config][:join] = { type: 'text', description: 'Join all of the events from this flux into one event, under this name.', default: '' }
49
- details[:config][:sort] = { type: 'text', description: 'Sort by this key.', default: '' }
50
- details[:config][:model] = { type: 'keyvalue', description: 'Reshape the outgoing events.', value: {}, default: {} }
52
+ details[:config][:incoming_split] = { type: 'text', shrink: true, description: 'Split an incoming event into multiple events by this key, an each event will be processed independently.', default: '' }
53
+ details[:config][:outgoing_split] = { type: 'text', shrink: true, description: 'Split an outgoing event into multiple events by this key.', default: '' }
54
+ details[:config][:merge] = { type: 'text', shrink: true, description: 'A comma-delimited list of fields from the event to carry through. Use * to merge all fields.', default: '' }
55
+ details[:config][:group] = { type: 'text', shrink: true, description: 'Group events by a field, which is stored in a key. The format is group_by|group_key.', default: '' }
56
+ details[:config][:limit] = { type: 'integer', shrink: true, description: 'Limit the number of events to this number.', default: '' }
57
+ details[:config][:join] = { type: 'text', shrink: true, description: 'Join all of the events from this flux into one event, under this name.', default: '' }
58
+ details[:config][:sort] = { type: 'text', shrink: true, description: 'Sort by this key.', default: '' }
59
+ details[:config][:model] = { type: 'keyvalue', shrink: true, description: 'Reshape the outgoing events.', value: {}, default: {} }
51
60
 
52
61
  details[:config]
53
62
  .select { |_, v| v[:type] == 'keyvalue' }
@@ -12,19 +12,28 @@ module Mushy
12
12
  </head>
13
13
  <body>
14
14
  <div id="app">
15
- <table>
15
+ <table v-if="setup.showFlux == false">
16
+ <tr>
17
+ <th>Name</th>
18
+ <th>Receives Events From</th>
19
+ <th>Actions</th>
20
+ </tr>
16
21
  <tr v-for="flux in flow.fluxs">
17
22
  <td>{{flux.name}}</td>
18
- <td>{{flux.flux}}</td>
19
- <td><a href="#" v-on:click.prevent.stop="edit({ flux: flux, setup: setup, configs: configs })">[Edit]</a></td>
23
+ <td>{{flux_name_for(flux.parent, flow.fluxs)}}</td>
24
+ <td>
25
+ <button v-on:click.prevent.stop="editFlux({ flux: flux, setup: setup, configs: configs })">Edit</button>
26
+ <button v-on:click.prevent.stop="deleteFlux({ flux: flux, flow: flow })">Delete</button>
27
+ </td>
20
28
  </tr>
21
29
  </table>
22
- <a href="#" v-if="setup.showFlux == false" v-on:click.prevent.stop="startNew({ setup: setup, configs: configs })">[New]</a>
23
- <a href="#" v-if="setup.showFlux == false" v-on:click.prevent.stop="saveFlow({ setup: setup, flow: flow })">[Save]</a>
30
+ <button v-if="setup.showFlux == false" v-on:click.prevent.stop="startNew({ setup: setup, configs: configs })">Start a New Flux</button>
31
+ <button v-if="setup.showFlux == false" v-on:click.prevent.stop="saveFlow({ setup: setup, flow: flow })">Save This Flow</button>
32
+ <button v-if="setup.showFlux" v-on:click.prevent.stop="setup.showFlux = false">&lt; Go Back To List</button>
24
33
  <div v-if="setup.showFlux">
25
34
  <mip-heavy :data="setup"></mip-heavy>
26
35
  <mip-heavy v-for="(data, id) in configs" v-show="setup.flux.value === id" :data="data"></mip-heavy>
27
- <div v-if="results.loading">Loading...</div>
36
+ <div v-if="results.errorMessage">{{results.errorMessage}}</div>
28
37
  <div v-else>{{results.length}} result{{results.length == 1 ? "" : "s"}}</div>
29
38
  <mip-heavy v-for="data in results" :data="data"></mip-heavy>
30
39
  </div>
@@ -48,28 +57,48 @@ module Mushy
48
57
 
49
58
  var components = {
50
59
  label: {
51
- props: ['label', 'description'],
52
- template: '<label :for="id" v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description">({{description}})</i></label>'
60
+ props: ['label', 'description', 'hide_description'],
61
+ template: '<label :for="id" v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></label>'
62
+ },
63
+ h1: {
64
+ props: ['label', 'description', 'hide_description'],
65
+ template: '<h1 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h1>'
66
+ },
67
+ h2: {
68
+ props: ['label', 'description', 'hide_description'],
69
+ template: '<h2 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h2>'
70
+ },
71
+ h3: {
72
+ props: ['label', 'description', 'hide_description'],
73
+ template: '<h3 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h3>'
74
+ },
75
+ h4: {
76
+ props: ['label', 'description', 'hide_description'],
77
+ template: '<h4 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h4>'
53
78
  },
54
79
  text: {
55
- props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
56
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><input type="text" :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
80
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
81
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><input type="text" :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
82
+ },
83
+ hide: {
84
+ props: ['label', 'description'],
85
+ template: '<mip-label :id="id" :label="label" :description="description" v-if="false"></mip-label>'
57
86
  },
58
87
  integer: {
59
- props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
60
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><input type="text" :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
88
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
89
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><input type="text" :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value);" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
61
90
  },
62
91
  email: {
63
- props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
64
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><input type="email" :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
92
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
93
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><input type="email" :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></div>'
65
94
  },
66
95
  textarea: {
67
- props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
68
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><textarea :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
96
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
97
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><textarea :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
69
98
  },
70
99
  json: {
71
- props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description'],
72
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><pre><code>{{value}}</code></pre><textarea :name="id" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
100
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
101
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><textarea :name="id" v-if="value || !shrink" :placeholder="placeholder" v-bind:value="value" v-on:input="$emit(\\'update:value\\', $event.target.value)" :disabled="disabled == \\'true\\'" :readonly="readonly == \\'true\\'"></textarea></div>'
73
102
  },
74
103
  jsonview: {
75
104
  data: function() {
@@ -80,23 +109,23 @@ module Mushy
80
109
  };
81
110
  },
82
111
  props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'view'],
83
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label> <a href="#" v-on:click.prevent.stop="view=toggle(view)">{{(view == \\'beautiful\\' ? \\'>\\' : \\'^\\')}}</a><a href="#" v-on:click.prevent.stop="copy(view, value)">copy</a><pre><code>{{show(view, value)}}</code></pre></div>'
112
+ template: '<div><mip-h4 :id="id" :label="label" :description="description"></mip-h4> <pre><code>{{show(view, value)}}</code></pre><button :disabled="view==\\'beautiful\\'" v-on:click.prevent.stop="view=toggle(view)">{{(view == \\'beautiful\\' ? \\'View Smaller\\' : \\'View Pretty\\')}}</button><button :disabled="view!=\\'beautiful\\'" v-on:click.prevent.stop="view=toggle(view)">View Smaller</button><button v-on:click.prevent.stop="copy(view, value)">Copy</button></div>'
84
113
  },
85
114
  radio: {
86
- props: ['label', 'value', 'options', 'description'],
87
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><div v-for="option in options"><input type="radio" :name="id" v-bind:value="option" v-on:input="$emit(\\'update:value\\', $event.target.value)" :checked="value == option"> <label for="option">{{option}}</label></div></div>'
115
+ props: ['label', 'value', 'options', 'description', 'shrink'],
116
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><div v-for="option in options"><input type="radio" :name="id" v-bind:value="option" v-if="value || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)" :checked="value == option"> <label for="option">{{option}}</label></div></div>'
88
117
  },
89
118
  select: {
90
- props: ['label', 'value', 'options', 'description'],
91
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><select :name="id" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
119
+ props: ['label', 'value', 'options', 'description', 'shrink'],
120
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><select :name="id" v-if="value || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
92
121
  },
93
122
  selectrecord: {
94
- props: ['label', 'value', 'options', 'description'],
95
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><select :name="id" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option.id" :selected="value == option.id">{{option.name}}</option></select></div>'
123
+ props: ['label', 'value', 'options', 'description', 'shrink'],
124
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><select :name="id" v-if="value || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in options" v-bind:value="option.id" :selected="value == option.id">{{option.name}}</option></select></div>'
96
125
  },
97
126
  boolean: {
98
- props: ['label', 'value', 'options', 'description'],
99
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><select :name="id" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in [true, false]" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
127
+ props: ['label', 'value', 'options', 'description', 'shrink'],
128
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && !value">[^]</a><select :name="id" v-if="(value != undefined && value != null && value != \\'\\') || !shrink" v-on:input="$emit(\\'update:value\\', $event.target.value)"><option v-for="option in [true, false]" v-bind:value="option" :selected="value == option">{{option}}</option></select></div>'
100
129
  },
101
130
  table: {
102
131
  props: ['value', 'description'],
@@ -117,12 +146,13 @@ module Mushy
117
146
  }
118
147
  };
119
148
  },
120
- props: ['value', 'editors', 'label', 'description'],
121
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><table><tr><th v-for="(d, i) in value[0]">{{' + fancyName('i') + '}}</th></tr><tr v-for="(v, z) in value"><td v-for="(d, i) in v">{{d}}</td><td><a href="#" v-on:click.prevent.stop="removeRecord(v, value, z)">[x]</a></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><a href="#" v-on:click.prevent.stop="addRecord(editors, value)">[Add]</a></td></tr></table></div>'
149
+ props: ['value', 'editors', 'label', 'description', 'shrink'],
150
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink && value.length == 0">[^]</a><table v-if="value.length > 0 || !shrink"><tr><th v-for="(d, i) in value[0]">{{' + fancyName('i') + '}}</th></tr><tr v-for="(v, z) in value"><td v-for="(d, i) in v">{{d}}</td><td><a href="#" v-on:click.prevent.stop="removeRecord(v, value, z)">[x]</a></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><a href="#" v-on:click.prevent.stop="addRecord(editors, value)">[Add]</a></td></tr></table></div>'
122
151
  },
123
152
  keyvalue: {
124
153
  data: function() {
125
154
  return {
155
+ actionText: function(value, others) { found = false; for(var i in others){ if (i == value) found = true; } return found ? 'Replace' : 'Add'; },
126
156
  removeRecord: function(data, key) { Vue.delete(data, key) },
127
157
  addRecord: function(editors, data) {
128
158
  Vue.set(data, editors[0].field.value, editors[1].field.value)
@@ -131,12 +161,12 @@ module Mushy
131
161
  }
132
162
  };
133
163
  },
134
- props: ['value', 'label', 'editors', 'description'],
135
- template: '<div><mip-label :id="id" :label="label" :description="description"></mip-label><table><tr v-for="(v, k) in value"><td>{{k}}</td><td>{{v}}</td><td><a href="#" v-on:click.prevent.stop="removeRecord(value, k)">[x]</a></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><a href="#" v-on:click.prevent.stop="addRecord(editors, value)" v-show="editors[0].field.value">[Add]</a></td></tr></table></div>'
164
+ props: ['value', 'label', 'editors', 'description', 'shrink'],
165
+ template: '<div><mip-label :id="id" :label="label" :description="description" :hide_description="shrink"></mip-label> <a href="#" v-on:click.prevent.stop="shrink=false" v-show="shrink">[^]</a><table v-if="JSON.stringify(value) != \\'{}\\' || !shrink"><tr v-for="(v, k) in value"><td>{{k}}</td><td>{{v}}</td><td><button v-on:click.prevent.stop="removeRecord(value, k)">Remove {{k}}</button></td></tr><tr><td v-for="editor in editors"><mip-thing :data="editor.field" :id="editor.id"></mip-thing></td><td><button v-on:click.prevent.stop="addRecord(editors, value)" v-show="editors[0].field.value">{{actionText(editors[0].field.value, value)}} {{editors[0].field.value}}</button></td></tr></table></div>'
136
166
  },
137
167
  button: {
138
- props: ['click', 'description'],
139
- template: '<button v-on:click.prevent.stop="click(pull(this))">{{id}}</button>'
168
+ props: ['click', 'description', 'name'],
169
+ template: '<button v-on:click.prevent.stop="click(pull(this), thisComponent())">{{name || id}}</button>'
140
170
  }
141
171
  };
142
172
 
@@ -156,6 +186,7 @@ module Mushy
156
186
  return {
157
187
  console: console,
158
188
  pull: function(x) { return thingToData(foundIt.data); },
189
+ thisComponent: function() { return foundIt.data; },
159
190
  }
160
191
  },
161
192
  props: props,
@@ -188,32 +219,6 @@ module Mushy
188
219
  template: '<div><mip-thing v-for="(d, id) in data" :data="d" :id="id"></mip-thing></div>',
189
220
  });
190
221
 
191
- var sample = {
192
- email: { type: 'email', value: 'darren@cauthon.com' },
193
- first_name: { type: 'text', value: 'Darren' },
194
- description: { type: 'textarea', value: 'more data' },
195
- size: { type: 'select', value: 'medium', options: ['small', 'medium', 'large']},
196
- heynow: { type: 'keyvalue',
197
- value: {
198
- first_name: 'John',
199
- last_name: 'Doe',
200
- },
201
- editors: [
202
- { id: 'new_key', target: 'key', field: { type: 'text', value: '', default: '' } },
203
- { id: 'new_value', target: 'value', field: { type: 'text', value: '', default: '' } }
204
- ] },
205
- past: { type: 'editgrid',
206
- value: [
207
- { name: 'Godzilla', quantity: 1 },
208
- { name: 'Mothra', quantity: 2 },
209
- ],
210
- editors: [
211
- { id: 'new_name', target: 'name', field: { type: 'text', value: '', default: '' } },
212
- { id: 'new_quantity', target: 'quantity', field: { type: 'select', value: '1', options: [1, 2, 3], default: 1 } }
213
- ] },
214
- super_action: { type: 'button', click: function(x) { console.log(x) } },
215
- };
216
-
217
222
  var app = null;
218
223
 
219
224
  axios.get('/fluxs')
@@ -237,51 +242,80 @@ module Mushy
237
242
 
238
243
  var setup = {
239
244
  showFlux: false,
240
- event: { type: 'json', value: '{}' },
241
- id: { type: 'text', value: '' },
245
+ id: { type: 'hide', value: '' },
242
246
  name: { type: 'text', value: '' },
243
247
  flux: { type: 'select', value: fluxdata.fluxs[0].name, options: options},
244
- parent: { type: 'selectrecord', value: '', options: flowdata.fluxs },
248
+ parent: { type: 'selectrecord', label: 'Receive Events From', value: '', options: flowdata.fluxs },
249
+ };
250
+
251
+ var saveFlux = function(config, hey) {
252
+ var nameOfTheSaveButton = hey.save.name;
253
+ Vue.set(hey.save, 'name', 'Saving');
254
+ delete config.test_event;
255
+ var setup = thingToData(app.setup);
256
+ var flux = {
257
+ id: setup.id,
258
+ name: setup.name,
259
+ flux: setup.flux,
260
+ parent: setup.parent,
261
+ config: config,
262
+ };
263
+ var index = -1;
264
+ for(var i = 0; i < app.flow.fluxs.length; i++)
265
+ if (app.flow.fluxs[i].id == flux.id)
266
+ index = i;
267
+
268
+ if (index < 0)
269
+ app.flow.fluxs.push(flux);
270
+ else
271
+ app.flow.fluxs[index] = flux;
272
+
273
+ setTimeout(function(){
274
+ Vue.set(hey.save, 'name', nameOfTheSaveButton);
275
+ app.setup.id.value = '';
276
+
277
+ Vue.set(app.setup, 'showFlux', false);
278
+ }, 500);
245
279
  };
246
280
 
247
281
  for (var key in configs)
248
282
  {
249
- configs[key].go = { type: 'button', click: function(c) {
283
+ configs[key].save = { type: 'button', name: 'Save This Flux', click: saveFlux };
284
+
285
+ configs[key].test_event = { type: 'json', value: '{}', default: '{}' };
286
+
287
+ configs[key].run_test = { type: 'button', name: 'Test Run This Flux', click: function(c, hey) {
288
+ var previousName = hey.run_test.name;
289
+ Vue.set(hey.run_test, 'name', 'Loading');
250
290
  app.results = [];
251
- Vue.set(app.results, 'loading', true);
252
- axios.post('/run', { config: c, setup: thingToData(app.setup) })
291
+ Vue.set(app.results, 'errorMessage', '');
292
+ var the_setup = thingToData(app.setup);
293
+ the_setup.event = c.test_event;
294
+ axios.post('/run', { config: c, setup: the_setup })
253
295
  .then(function(r){
254
- Vue.set(app.results, 'loading', false);
296
+ var index = 1;
255
297
  for (var key in r.data.result)
256
- app.results.push({darren: { type:'jsonview', value: r.data.result[key], view: 'thin' }});
298
+ {
299
+ var result = {};
300
+ result['event_' + index] = { type: 'jsonview', label: 'Event ' + index + ' of ' + r.data.result.length, value: r.data.result[key], view: 'thin' };
301
+ app.results.push(result);
302
+ index += 1;
303
+ }
304
+ }).catch(function(r){
305
+ console.log(r);
306
+ Vue.set(app.results, 'errorMessage', 'This app failed while trying to execute your flux.');
307
+ }).then(function(){
308
+ Vue.set(hey.run_test, 'name', previousName);
257
309
  });
258
310
  } };
259
-
260
- configs[key].save = { type: 'button', click: function(config) {
261
- var setup = thingToData(app.setup);
262
- var flux = {
263
- id: setup.id,
264
- name: setup.name,
265
- flux: setup.flux,
266
- parent: setup.parent,
267
- config: config,
268
- };
269
- var index = -1;
270
- for(var i = 0; i < app.flow.fluxs.length; i++)
271
- if (app.flow.fluxs[i].id == flux.id)
272
- index = i;
273
- if (index < 0)
274
- app.flow.fluxs.push(flux);
275
- else
276
- app.flow.fluxs[index] = flux;
277
-
278
- app.setup.id.value = '';
279
- }
280
- };
281
311
  }
282
312
 
283
- var loadThisFlux = function(flux, setup, config)
313
+ var loadThisFlux = function(args)
284
314
  {
315
+ var flux = args.flux;
316
+ var setup = args.setup;
317
+ var config = args.config;
318
+
285
319
  Vue.set(setup.id, 'value', flux.id);
286
320
  Vue.set(setup.name, 'value', flux.name);
287
321
  Vue.set(setup.flux, 'value', flux.flux);
@@ -294,12 +328,15 @@ module Mushy
294
328
  else
295
329
  Vue.set(applicable_config[key], 'value', applicable_config[key].default);
296
330
 
331
+ if (applicable_config)
332
+ Vue.set(applicable_config.test_event, 'value', '{}');
297
333
 
298
334
  options = flowdata.fluxs.filter(function(x){ return x.id != flux.id });
299
335
  options.unshift( { id: '', name: '' } );
300
336
  setup.parent.options = options;
301
337
 
302
338
  Vue.set(setup, 'showFlux', true);
339
+ app.results = [];
303
340
  };
304
341
 
305
342
  function uuidv4() {
@@ -315,15 +352,19 @@ module Mushy
315
352
  startNew: function(x) {
316
353
  flux = {
317
354
  id: uuidv4(),
318
- name: 'you',
355
+ name: '',
319
356
  config: {}
320
357
  };
321
- loadThisFlux(flux, x.setup, x.configs);
358
+ loadThisFlux({ flux: flux, setup: x.setup, configs: x.configs });
322
359
  },
323
- edit: function(x) {
360
+ editFlux: function(x) {
324
361
  var flux = x.flux;
325
362
 
326
- loadThisFlux(x.flux, x.setup, x.configs);
363
+ loadThisFlux({ flux: x.flux, setup: x.setup, configs: x.configs });
364
+ },
365
+ deleteFlux: function(x) {
366
+ var set = x.flow.fluxs.filter( function(v){ return v.id != x.flux.id } );
367
+ Vue.set(x.flow, 'fluxs', set);
327
368
  },
328
369
  saveFlow: function(input)
329
370
  {
@@ -331,11 +372,15 @@ module Mushy
331
372
  var flow = input.flow;
332
373
  axios.post('/save', flow)
333
374
  .then(function(result){
334
- Vue.set(setup, 'show', false);
375
+ Vue.set(setup, 'showFlux', false);
335
376
  });
336
377
  },
337
378
  configs: configs,
338
379
  setup: setup,
380
+ flux_name_for: function(id, fluxes) {
381
+ var flux = fluxes.filter(function(x){ return x.id == id })[0];
382
+ return flux != undefined ? flux.name : '';
383
+ },
339
384
  results: [],
340
385
  }
341
386
  });
data/lib/mushy/flow.rb CHANGED
@@ -18,8 +18,10 @@ module Mushy
18
18
  end
19
19
 
20
20
  def self.build_flux record
21
- flux = Object.const_get("Mushy::#{record[:type] || record['type'] || 'Flux'}").new
21
+ type = record[:type] || record['type'] || record[:flux] || record['flux'] || 'Flux'
22
+ flux = Object.const_get("Mushy::#{type}").new
22
23
  flux.id = record[:id] || record['id'] || flux.id
24
+ flux.type = type
23
25
  flux.config = SymbolizedHash.new(record[:config] || record['config'])
24
26
  flux
25
27
  end
data/lib/mushy/flux.rb CHANGED
@@ -3,6 +3,7 @@ module Mushy
3
3
  class Flux
4
4
 
5
5
  attr_accessor :id
6
+ attr_accessor :type
6
7
  attr_accessor :parent_fluxs
7
8
  attr_accessor :subscribed_to
8
9
  attr_accessor :config
@@ -17,16 +17,25 @@ module Mushy
17
17
  headless: {
18
18
  description: 'Run this browser headless.',
19
19
  type: 'boolean',
20
+ shrink: true,
20
21
  value: 'true',
21
22
  },
23
+ timeout: {
24
+ description: 'The default timeout (in seconds) before closing the browser. Default is 5 seconds.',
25
+ type: 'integer',
26
+ shrink: true,
27
+ value: '',
28
+ },
22
29
  execute: {
23
30
  description: 'Javascript to run after the page is loaded.',
24
31
  type: 'textarea',
32
+ shrink: true,
25
33
  value: '',
26
34
  },
27
35
  cookies: {
28
36
  description: 'Cookies for the web request. These can be received from a previous browser event with {{cookies}}, or can be typed manually.',
29
37
  type: 'editgrid',
38
+ shrink: true,
30
39
  value: [],
31
40
  editors: [
32
41
  { id: 'name', target: 'name', field: { type: 'text', value: '', default: '' } },
@@ -40,27 +49,30 @@ module Mushy
40
49
  { id: 'sameSite', target: 'sameSite', field: { type: 'text', value: 'None', default: 'None' } },
41
50
  { id: 'priority', target: 'priority', field: { type: 'text', value: 'Medium', default: 'Medium' } },
42
51
  ],
43
- #{"name":"1P_JAR","value":"2021-01-21-13","domain":".google.com","path":"/","expires":1613828458.870408,"size":19,"httpOnly":false,"secure":true,"session":false,"sameSite":"None","priority":"Medium"
44
52
  },
45
53
  carry_cookies_from: {
46
54
  description: 'Carry the cookies from this path in the event.',
47
55
  type: 'text',
56
+ shrink: true,
48
57
  value: 'cookies',
49
58
  },
50
59
  headers: {
51
60
  description: 'Headers for the web request. These can be received from a previous browser event with {{headers}}, or can be typed manually.',
52
61
  type: 'keyvalue',
62
+ shrink: true,
53
63
  value: {},
54
64
  },
55
65
  carry_headers_from: {
56
66
  description: 'Carry the headers from this path in the event.',
57
67
  type: 'text',
68
+ shrink: true,
58
69
  value: 'headers',
59
70
  },
60
71
  wait_before_closing: {
61
72
  description: 'Wait this many seconds before closing the browser.',
62
73
  type: 'integer',
63
- value: 'cookies',
74
+ shrink: true,
75
+ value: '',
64
76
  },
65
77
  },
66
78
  }
@@ -68,7 +80,11 @@ module Mushy
68
80
 
69
81
  def process event, config
70
82
 
71
- browser = Ferrum::Browser.new(headless: (config[:headless].to_s != 'false'))
83
+ timeout = config[:timeout] ? config[:timeout].to_i : 5
84
+
85
+ browser = Ferrum::Browser.new(
86
+ headless: (config[:headless].to_s != 'false'),
87
+ timeout: timeout)
72
88
 
73
89
  get_the_cookies_from(event, config).each { |c| browser.cookies.set(c) }
74
90
 
@@ -78,15 +94,17 @@ module Mushy
78
94
 
79
95
  browser.execute(config[:execute]) if config[:execute]
80
96
 
97
+ sleep(config[:wait_before_closing].to_i) if config[:wait_before_closing] && config[:wait_before_closing].to_i > 0
98
+
81
99
  result = {
82
100
  url: browser.url,
101
+ status: browser.network.status,
102
+ title: browser.frames[0].title,
83
103
  cookies: browser.cookies.all.map { |k, v| v.instance_variable_get('@attributes') },
84
104
  headers: browser.headers.get,
85
105
  body: browser.body
86
106
  }
87
107
 
88
- sleep(config[:wait_before_closing].to_i) if config[:wait_before_closing] && config[:wait_before_closing].to_i > 0
89
-
90
108
  browser.quit
91
109
 
92
110
  result
@@ -0,0 +1,20 @@
1
+ module Mushy
2
+
3
+ class Cli < Flux
4
+
5
+ def self.details
6
+ {
7
+ name: 'Cli',
8
+ description: 'Accept CLI arguments from the run command.',
9
+ config: {
10
+ },
11
+ }
12
+ end
13
+
14
+ def process event, config
15
+ event
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -2,6 +2,29 @@ module Mushy
2
2
 
3
3
  class Filter < Flux
4
4
 
5
+ def self.details
6
+ {
7
+ name: 'Filter',
8
+ description: 'Filters events based on criteria.',
9
+ config: {
10
+ equal: {
11
+ description: 'Provide key/value pairs that must match in the event.',
12
+ shrink: true,
13
+ label: 'Equal To',
14
+ type: 'keyvalue',
15
+ value: {},
16
+ },
17
+ notequal: {
18
+ description: 'Provide key/value pairs that must NOT match in the event.',
19
+ shrink: true,
20
+ label: 'Not Equal To',
21
+ type: 'keyvalue',
22
+ value: {},
23
+ },
24
+ },
25
+ }
26
+ end
27
+
5
28
  def process event, config
6
29
 
7
30
  differences = [:equal, :notequal]
data/mushy.gemspec CHANGED
@@ -4,7 +4,7 @@ require 'mushy/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'mushy'
7
- s.version = '0.0.5'
7
+ s.version = '0.1.4'
8
8
  s.date = '2020-11-23'
9
9
  s.summary = 'Process streams of work using common modules.'
10
10
  s.description = 'This tool assists in the creation and processing of workflows.'
@@ -17,9 +17,11 @@ Gem::Specification.new do |s|
17
17
  s.license = 'MIT'
18
18
 
19
19
  s.add_development_dependency 'minitest'
20
+ s.add_runtime_dependency 'sinatra'
21
+ s.add_runtime_dependency 'symbolized'
20
22
  s.add_runtime_dependency 'thor'
21
23
  s.add_runtime_dependency 'liquid'
22
24
  s.add_runtime_dependency 'ferrum'
23
25
  s.add_runtime_dependency 'nokogiri'
24
26
  s.add_runtime_dependency 'faraday'
25
- end
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mushy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Darren Cauthon
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: symbolized
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: thor
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -114,6 +142,7 @@ files:
114
142
  - lib/mushy/fluxs/bash.rb
115
143
  - lib/mushy/fluxs/browser.rb
116
144
  - lib/mushy/fluxs/build_csv.rb
145
+ - lib/mushy/fluxs/cli.rb
117
146
  - lib/mushy/fluxs/collection.rb
118
147
  - lib/mushy/fluxs/filter.rb
119
148
  - lib/mushy/fluxs/format.rb