mushy 0.0.5 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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