mushy 0.0.4 → 0.1.3

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: 71665a3fd5c65c00c14b7bafd3ec2c40b13ec117e2469b6773c6c2a967fecd06
4
- data.tar.gz: 9b1886ac83b57eadaf08325017b71d31e17f649523ef62b2f7ae50ba6d17e3c0
3
+ metadata.gz: 5f516df95fc3919dd7d02ffe32228fd96364c06a56595ae8a7e986d406abc3af
4
+ data.tar.gz: c2dc07c4f8ad462134d674aeb4006eeabff5a07abee0d20d1ec5ff89312f80e7
5
5
  SHA512:
6
- metadata.gz: c8d72cf3f86672225afdb716b5a2e7142b572a0318db68fb029c16d74ebed9207cc23509ef37200d5b7df7de5cc364aa94b3e8178374b07b75d77312cfc2c913
7
- data.tar.gz: 0ee8fa16d84152f5e9351b760d439c481d201c1e32c6ecc6112416a9857c74f9dd4a0c1c26ee3402b2daa9bb44961c917720bb2f2d9c4a2d67f8f7cdd8fb8983
6
+ metadata.gz: b2e8a4bc112300daeb8089a455c10ef7c6842524a0a8dc3a00aa0c8715ecee836eff17f89c461ead76ae4ba716c56e49e436be57e8f163de3a57d8fe8249e816
7
+ data.tar.gz: ef23272c88796185deb60fd11ad9a326b3dd4a84d2df7aa86830727e72408811eda47a2fb13e59cb481b6a0fb0ad505a7ee4c606cf50b6478e7dc0d7303c0371
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
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.id.value == ''" v-on:click.prevent.stop="startNew({ setup: setup, configs: configs })">[New]</a>
23
- <a href="#" v-if="setup.id.value == ''" v-on:click.prevent.stop="saveFlow(flow)">[Save]</a>
24
- <div v-if="setup.id.value">
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>
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,19 +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>'
121
+ },
122
+ selectrecord: {
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>'
92
125
  },
93
126
  boolean: {
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 [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>'
96
129
  },
97
130
  table: {
98
131
  props: ['value', 'description'],
@@ -113,12 +146,13 @@ module Mushy
113
146
  }
114
147
  };
115
148
  },
116
- props: ['value', 'editors', 'label', 'description'],
117
- 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>'
118
151
  },
119
152
  keyvalue: {
120
153
  data: function() {
121
154
  return {
155
+ actionText: function(value, others) { found = false; for(var i in others){ if (i == value) found = true; } return found ? 'Replace' : 'Add'; },
122
156
  removeRecord: function(data, key) { Vue.delete(data, key) },
123
157
  addRecord: function(editors, data) {
124
158
  Vue.set(data, editors[0].field.value, editors[1].field.value)
@@ -127,12 +161,12 @@ module Mushy
127
161
  }
128
162
  };
129
163
  },
130
- props: ['value', 'label', 'editors', 'description'],
131
- 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>'
132
166
  },
133
167
  button: {
134
- props: ['click', 'description'],
135
- 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>'
136
170
  }
137
171
  };
138
172
 
@@ -152,6 +186,7 @@ module Mushy
152
186
  return {
153
187
  console: console,
154
188
  pull: function(x) { return thingToData(foundIt.data); },
189
+ thisComponent: function() { return foundIt.data; },
155
190
  }
156
191
  },
157
192
  props: props,
@@ -184,32 +219,6 @@ module Mushy
184
219
  template: '<div><mip-thing v-for="(d, id) in data" :data="d" :id="id"></mip-thing></div>',
185
220
  });
186
221
 
187
- var sample = {
188
- email: { type: 'email', value: 'darren@cauthon.com' },
189
- first_name: { type: 'text', value: 'Darren' },
190
- description: { type: 'textarea', value: 'more data' },
191
- size: { type: 'select', value: 'medium', options: ['small', 'medium', 'large']},
192
- heynow: { type: 'keyvalue',
193
- value: {
194
- first_name: 'John',
195
- last_name: 'Doe',
196
- },
197
- editors: [
198
- { id: 'new_key', target: 'key', field: { type: 'text', value: '', default: '' } },
199
- { id: 'new_value', target: 'value', field: { type: 'text', value: '', default: '' } }
200
- ] },
201
- past: { type: 'editgrid',
202
- value: [
203
- { name: 'Godzilla', quantity: 1 },
204
- { name: 'Mothra', quantity: 2 },
205
- ],
206
- editors: [
207
- { id: 'new_name', target: 'name', field: { type: 'text', value: '', default: '' } },
208
- { id: 'new_quantity', target: 'quantity', field: { type: 'select', value: '1', options: [1, 2, 3], default: 1 } }
209
- ] },
210
- super_action: { type: 'button', click: function(x) { console.log(x) } },
211
- };
212
-
213
222
  var app = null;
214
223
 
215
224
  axios.get('/fluxs')
@@ -232,27 +241,19 @@ module Mushy
232
241
  options.push(fluxTypes[type]);
233
242
 
234
243
  var setup = {
235
- event: { type: 'json', value: '{}' },
236
- id: { type: 'text', value: '' },
244
+ showFlux: false,
245
+ id: { type: 'hide', value: '' },
237
246
  name: { type: 'text', value: '' },
238
247
  flux: { type: 'select', value: fluxdata.fluxs[0].name, options: options},
239
- parent: { type: 'select', value: '', options: flowdata.fluxs.map(function(x) { return x.id; }) },
248
+ parent: { type: 'selectrecord', label: 'Receive Events From', value: '', options: flowdata.fluxs },
240
249
  };
241
250
 
242
251
  for (var key in configs)
243
252
  {
244
- configs[key].go = { type: 'button', click: function(c) {
245
- app.results = [];
246
- Vue.set(app.results, 'loading', true);
247
- axios.post('/run', { config: c, setup: thingToData(app.setup) })
248
- .then(function(r){
249
- Vue.set(app.results, 'loading', false);
250
- for (var key in r.data.result)
251
- app.results.push({darren: { type:'jsonview', value: r.data.result[key], view: 'thin' }});
252
- });
253
- } };
254
-
255
- configs[key].save = { type: 'button', click: function(config) {
253
+ configs[key].save = { type: 'button', name: 'Save This Flux', click: function(config, hey) {
254
+ var nameOfTheSaveButton = hey.save.name;
255
+ Vue.set(hey.save, 'name', 'Saving');
256
+ delete config.test_event;
256
257
  var setup = thingToData(app.setup);
257
258
  var flux = {
258
259
  id: setup.id,
@@ -270,13 +271,49 @@ module Mushy
270
271
  else
271
272
  app.flow.fluxs[index] = flux;
272
273
 
273
- app.setup.id.value = '';
274
+ setTimeout(function(){
275
+ Vue.set(hey.save, 'name', nameOfTheSaveButton);
276
+ app.setup.id.value = '';
277
+
278
+ Vue.set(app.setup, 'showFlux', false);
279
+ }, 500);
274
280
  }
275
281
  };
282
+
283
+ configs[key].test_event = { type: 'json', value: '{}', default: '{}' };
284
+
285
+ configs[key].run_test = { type: 'button', name: 'Test Run This Flux', click: function(c, hey) {
286
+ var previousName = hey.run_test.name;
287
+ Vue.set(hey.run_test, 'name', 'Loading');
288
+ app.results = [];
289
+ Vue.set(app.results, 'errorMessage', '');
290
+ var the_setup = thingToData(app.setup);
291
+ the_setup.event = c.test_event;
292
+ axios.post('/run', { config: c, setup: the_setup })
293
+ .then(function(r){
294
+ var index = 1;
295
+ for (var key in r.data.result)
296
+ {
297
+ var result = {};
298
+ result['event_' + index] = { type: 'jsonview', label: 'Event ' + index + ' of ' + r.data.result.length, value: r.data.result[key], view: 'thin' };
299
+ app.results.push(result);
300
+ index += 1;
301
+ }
302
+ }).catch(function(r){
303
+ console.log(r);
304
+ Vue.set(app.results, 'errorMessage', 'This app failed while trying to execute your flux.');
305
+ }).then(function(){
306
+ Vue.set(hey.run_test, 'name', previousName);
307
+ });
308
+ } };
276
309
  }
277
310
 
278
- var loadThisFlux = function(flux, setup, config)
311
+ var loadThisFlux = function(args)
279
312
  {
313
+ var flux = args.flux;
314
+ var setup = args.setup;
315
+ var config = args.config;
316
+
280
317
  Vue.set(setup.id, 'value', flux.id);
281
318
  Vue.set(setup.name, 'value', flux.name);
282
319
  Vue.set(setup.flux, 'value', flux.flux);
@@ -289,39 +326,59 @@ module Mushy
289
326
  else
290
327
  Vue.set(applicable_config[key], 'value', applicable_config[key].default);
291
328
 
329
+ if (applicable_config)
330
+ Vue.set(applicable_config.test_event, 'value', '{}');
292
331
 
293
- options = flowdata.fluxs.map(function(x) { return x.id; }).filter(function(x){ return x != flux.id });
294
- options.unshift('');
332
+ options = flowdata.fluxs.filter(function(x){ return x.id != flux.id });
333
+ options.unshift( { id: '', name: '' } );
295
334
  setup.parent.options = options;
335
+
336
+ Vue.set(setup, 'showFlux', true);
337
+ app.results = [];
296
338
  };
297
339
 
340
+ function uuidv4() {
341
+ return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
342
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
343
+ );
344
+ }
345
+
298
346
  app = new Vue({
299
347
  el: '#app',
300
348
  data: {
301
349
  flow: flowdata,
302
350
  startNew: function(x) {
303
351
  flux = {
304
- id: 'hey',
305
- name: 'you',
352
+ id: uuidv4(),
353
+ name: '',
306
354
  config: {}
307
355
  };
308
- loadThisFlux(flux, x.setup, x.configs);
356
+ loadThisFlux({ flux: flux, setup: x.setup, configs: x.configs });
309
357
  },
310
- edit: function(x) {
358
+ editFlux: function(x) {
311
359
  var flux = x.flux;
312
360
 
313
- loadThisFlux(x.flux, x.setup, x.configs);
361
+ loadThisFlux({ flux: x.flux, setup: x.setup, configs: x.configs });
362
+ },
363
+ deleteFlux: function(x) {
364
+ var set = x.flow.fluxs.filter( function(v){ return v.id != x.flux.id } );
365
+ Vue.set(x.flow, 'fluxs', set);
314
366
  },
315
- saveFlow: function(flow)
367
+ saveFlow: function(input)
316
368
  {
317
- console.log(flow);
369
+ var setup = input.setup;
370
+ var flow = input.flow;
318
371
  axios.post('/save', flow)
319
372
  .then(function(result){
320
- console.log(result);
373
+ Vue.set(setup, 'showFlux', false);
321
374
  });
322
375
  },
323
376
  configs: configs,
324
377
  setup: setup,
378
+ flux_name_for: function(id, fluxes) {
379
+ var flux = fluxes.filter(function(x){ return x.id == id })[0];
380
+ return flux != undefined ? flux.name : '';
381
+ },
325
382
  results: [],
326
383
  }
327
384
  });
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,30 +49,42 @@ 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
  },
71
+ wait_before_closing: {
72
+ description: 'Wait this many seconds before closing the browser.',
73
+ type: 'integer',
74
+ shrink: true,
75
+ value: '',
76
+ },
60
77
  },
61
78
  }
62
79
  end
63
80
 
64
81
  def process event, config
65
82
 
66
- 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)
67
88
 
68
89
  get_the_cookies_from(event, config).each { |c| browser.cookies.set(c) }
69
90
 
@@ -73,8 +94,12 @@ module Mushy
73
94
 
74
95
  browser.execute(config[:execute]) if config[:execute]
75
96
 
97
+ sleep(config[:wait_before_closing].to_i) if config[:wait_before_closing] && config[:wait_before_closing].to_i > 0
98
+
76
99
  result = {
77
100
  url: browser.url,
101
+ status: browser.network.status,
102
+ title: browser.frames[0].title,
78
103
  cookies: browser.cookies.all.map { |k, v| v.instance_variable_get('@attributes') },
79
104
  headers: browser.headers.get,
80
105
  body: browser.body
@@ -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.4'
7
+ s.version = '0.1.3'
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.4
4
+ version: 0.1.3
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