mushy 0.0.6 → 0.2.0

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: d600a02a01a8ab0b72d853e0756b8abab002072eb97435e1502f159c34b1d22d
4
- data.tar.gz: 506d0ae442e3c44c877af2f7474792e6c8e4bd1c79ecde3f9b7917bb84817c5d
3
+ metadata.gz: dc571150c0fa3c2315c75186d48836987ca92d93045de5af848fe450c975a039
4
+ data.tar.gz: cbd83a5b9fa9c0106b6891afa33eeb16ddd947bba61c62f13b6ff7e7a574ee0e
5
5
  SHA512:
6
- metadata.gz: 1170524f5a821ce6a35d4fc65b4672371ec5c21940c113d7eb41d5397c94c0d804ec6a10f6bc1c8e6508c1093917afe030b12353a7f1c7fdb8a1635bda62f463
7
- data.tar.gz: 62a78ba547cbe18846dc0308ab48d3460ab2c201afe93e09410febde8e6932c8475e619be31e657531504d441a816a295a3e0a128503c2f2917f47b3a24261ef
6
+ metadata.gz: 720fb42b4b3df8d46cd7e26a87b793e0d41111f12652d588c0378160a00af08de05bedcb32920d1ce01c2c0efe135caaa48a939edd6b25822f8383cac3acdd1a
7
+ data.tar.gz: 1707b73e264d067362a7bd00e48558a9981c807319ff925e92c4fc829cbf8129aac14f31dd0edaba53354893de2ec4be633eebe9da2d882ec568a6394e852d9f
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
data/lib/mushy.rb CHANGED
@@ -8,10 +8,4 @@ Dir[File.dirname(__FILE__) + '/mushy/fluxs/*.rb']
8
8
  .sort_by { |f| important_flux_files.any? { |x| f.end_with?(x) } ? 0 : 1 }
9
9
  .each { |f| require f }
10
10
 
11
- Dir[File.dirname(__FILE__) + '/mushy/builder/*.rb'].each { |f| require f }
12
-
13
- module Mushy
14
- def self.hi
15
- puts 'hello'
16
- end
17
- end
11
+ Dir[File.dirname(__FILE__) + '/mushy/builder/*.rb'].each { |f| require f }
@@ -28,10 +28,29 @@ 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')
34
- JSON.parse File.open(file).read
43
+ data = JSON.parse File.open(file).read
44
+ data['fluxs']
45
+ .reject { |x| x['parents'] }
46
+ .each { |x| x['parents'] = [x['parent']].select { |y| y } }
47
+ data['fluxs']
48
+ .select { |x| x['parent'] }
49
+ .each { |x| x.delete 'parent' }
50
+ data['fluxs']
51
+ .select { |x| x['parents'] }
52
+ .each { |x| x['parents'] = x['parents'].select { |y| y } }
53
+ data
35
54
  rescue
36
55
  { fluxs: [] }
37
56
  end
@@ -40,14 +59,14 @@ module Mushy
40
59
  {
41
60
  fluxs: Mushy::Flux.all.select { |x| x.respond_to? :details }.map do |flux|
42
61
  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: {} }
62
+ 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: '' }
63
+ details[:config][:outgoing_split] = { type: 'text', shrink: true, description: 'Split an outgoing event into multiple events by this key.', default: '' }
64
+ 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: '' }
65
+ 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: '' }
66
+ details[:config][:limit] = { type: 'integer', shrink: true, description: 'Limit the number of events to this number.', default: '' }
67
+ details[:config][:join] = { type: 'text', shrink: true, description: 'Join all of the events from this flux into one event, under this name.', default: '' }
68
+ details[:config][:sort] = { type: 'text', shrink: true, description: 'Sort by this key.', default: '' }
69
+ details[:config][:model] = { type: 'keyvalue', shrink: true, description: 'Reshape the outgoing events.', value: {}, default: {} }
51
70
 
52
71
  details[:config]
53
72
  .select { |_, v| v[:type] == 'keyvalue' }
@@ -12,19 +12,26 @@ 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.parents, 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 })">Add a New Flux To This Flow</button>
24
31
  <div v-if="setup.showFlux">
25
32
  <mip-heavy :data="setup"></mip-heavy>
26
33
  <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>
34
+ <div v-if="results.errorMessage">{{results.errorMessage}}</div>
28
35
  <div v-else>{{results.length}} result{{results.length == 1 ? "" : "s"}}</div>
29
36
  <mip-heavy v-for="data in results" :data="data"></mip-heavy>
30
37
  </div>
@@ -48,28 +55,48 @@ module Mushy
48
55
 
49
56
  var components = {
50
57
  label: {
51
- props: ['label', 'description'],
52
- template: '<label :for="id" v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description">({{description}})</i></label>'
58
+ props: ['label', 'description', 'hide_description'],
59
+ template: '<label :for="id" v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></label>'
60
+ },
61
+ h1: {
62
+ props: ['label', 'description', 'hide_description'],
63
+ template: '<h1 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h1>'
64
+ },
65
+ h2: {
66
+ props: ['label', 'description', 'hide_description'],
67
+ template: '<h2 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h2>'
68
+ },
69
+ h3: {
70
+ props: ['label', 'description', 'hide_description'],
71
+ template: '<h3 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h3>'
72
+ },
73
+ h4: {
74
+ props: ['label', 'description', 'hide_description'],
75
+ template: '<h4 v-if="label != \\'\\'">{{label || ' + fancyName('id') + '}} <i v-show="description && !hide_description">({{description}})</i></h4>'
53
76
  },
54
77
  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>'
78
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
79
+ 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>'
80
+ },
81
+ hide: {
82
+ props: ['label', 'description'],
83
+ template: '<mip-label :id="id" :label="label" :description="description" v-if="false"></mip-label>'
57
84
  },
58
85
  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>'
86
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
87
+ 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
88
  },
62
89
  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>'
90
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
91
+ 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
92
  },
66
93
  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>'
94
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
95
+ 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
96
  },
70
97
  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>'
98
+ props: ['label', 'placeholder', 'disabled', 'readonly', 'value', 'description', 'shrink'],
99
+ 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
100
  },
74
101
  jsonview: {
75
102
  data: function() {
@@ -80,23 +107,49 @@ module Mushy
80
107
  };
81
108
  },
82
109
  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>'
110
+ 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
111
  },
85
112
  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>'
113
+ props: ['label', 'value', 'options', 'description', 'shrink'],
114
+ 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
115
  },
89
116
  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>'
117
+ props: ['label', 'value', 'options', 'description', 'shrink'],
118
+ 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
119
  },
93
120
  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>'
121
+ props: ['label', 'value', 'options', 'description', 'shrink'],
122
+ 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>'
123
+ },
124
+ selectmanyrecords: {
125
+ data: function() {
126
+ return {
127
+ selectedValue: '',
128
+ remove: function(value, set) {
129
+ if (set.includes(value) == false) return;
130
+ for(var i = 0; i < set.length; i++)
131
+ {
132
+ if (set[i] === value)
133
+ {
134
+ set.splice(i, 1);
135
+ i--;
136
+ }
137
+ }
138
+ return set;
139
+ },
140
+ doit: function(value, set) {
141
+ if (set.includes(value) == false)
142
+ set.push(value);
143
+ return set;
144
+ },
145
+ };
146
+ },
147
+ props: ['label', 'value', 'options', 'description', 'shrink'],
148
+ 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> <span v-for="option in options" v-if="value && value.includes(option.id)">{{option.name}} <a href="#" v-on:click.prevent.stop="remove(option.id, value);$emit(\\'update:value\\', value)">[X]</a> </span> <a href="#" v-on:click.prevent.stop="doit(selectedValue, value);$emit(\\'update:value\\', value)">ADD</a> <select :name="id" v-if="value || !shrink" v-on:input="selectedValue=$event.target.value;"><option v-for="option in options" v-bind:value="option.id">{{option.name}}</option></select></div>'
96
149
  },
97
150
  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>'
151
+ props: ['label', 'value', 'options', 'description', 'shrink'],
152
+ 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
153
  },
101
154
  table: {
102
155
  props: ['value', 'description'],
@@ -117,12 +170,13 @@ module Mushy
117
170
  }
118
171
  };
119
172
  },
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>'
173
+ props: ['value', 'editors', 'label', 'description', 'shrink'],
174
+ 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
175
  },
123
176
  keyvalue: {
124
177
  data: function() {
125
178
  return {
179
+ actionText: function(value, others) { found = false; for(var i in others){ if (i == value) found = true; } return found ? 'Replace' : 'Add'; },
126
180
  removeRecord: function(data, key) { Vue.delete(data, key) },
127
181
  addRecord: function(editors, data) {
128
182
  Vue.set(data, editors[0].field.value, editors[1].field.value)
@@ -131,12 +185,12 @@ module Mushy
131
185
  }
132
186
  };
133
187
  },
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>'
188
+ props: ['value', 'label', 'editors', 'description', 'shrink'],
189
+ 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
190
  },
137
191
  button: {
138
- props: ['click', 'description'],
139
- template: '<button v-on:click.prevent.stop="click(pull(this))">{{id}}</button>'
192
+ props: ['click', 'description', 'name'],
193
+ template: '<button v-on:click.prevent.stop="click(pull(this), thisComponent())">{{name || id}}</button>'
140
194
  }
141
195
  };
142
196
 
@@ -156,6 +210,7 @@ module Mushy
156
210
  return {
157
211
  console: console,
158
212
  pull: function(x) { return thingToData(foundIt.data); },
213
+ thisComponent: function() { return foundIt.data; },
159
214
  }
160
215
  },
161
216
  props: props,
@@ -188,32 +243,6 @@ module Mushy
188
243
  template: '<div><mip-thing v-for="(d, id) in data" :data="d" :id="id"></mip-thing></div>',
189
244
  });
190
245
 
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
246
  var app = null;
218
247
 
219
248
  axios.get('/fluxs')
@@ -235,57 +264,103 @@ module Mushy
235
264
  for(var type in fluxTypes)
236
265
  options.push(fluxTypes[type]);
237
266
 
267
+ var saveTheFlux = function(input)
268
+ {
269
+ var theApp = input.app;
270
+ var config = input.config;
271
+ delete config.test_event;
272
+ var setup = thingToData(theApp.setup);
273
+ var flux = {
274
+ id: setup.id,
275
+ name: setup.name,
276
+ flux: setup.flux,
277
+ parents: setup.parents,
278
+ config: config,
279
+ };
280
+ var index = -1;
281
+ for(var i = 0; i < theApp.flow.fluxs.length; i++)
282
+ if (theApp.flow.fluxs[i].id == flux.id)
283
+ index = i;
284
+
285
+ if (index < 0)
286
+ theApp.flow.fluxs.push(flux);
287
+ else
288
+ theApp.flow.fluxs[index] = flux;
289
+ };
290
+
291
+ var saveTheFlow = function(input)
292
+ {
293
+ var setup = input.setup;
294
+ var flow = input.flow;
295
+ axios.post('/save', flow)
296
+ .then(function(result){});
297
+ };
298
+
299
+ var saveFlux = function(config) {
300
+ };
301
+
302
+ var ignoreFlux = function(config) {
303
+ };
304
+
238
305
  var setup = {
239
306
  showFlux: false,
240
- event: { type: 'json', value: '{}' },
241
- id: { type: 'text', value: '' },
307
+ id: { type: 'hide', value: '' },
242
308
  name: { type: 'text', value: '' },
243
309
  flux: { type: 'select', value: fluxdata.fluxs[0].name, options: options},
244
- parent: { type: 'selectrecord', value: '', options: flowdata.fluxs },
310
+ parents: { type: 'selectmanyrecords', label: 'Receive Events From', value: '', options: flowdata.fluxs },
245
311
  };
246
312
 
247
313
  for (var key in configs)
248
314
  {
249
- configs[key].go = { type: 'button', click: function(c) {
315
+ configs[key].save = { type: 'button', name: 'Save Changes', click: function(config) {
316
+ saveTheFlux({ app: app, config: config });
317
+ saveTheFlow({ setup: app.setup, flow: app.flow });
318
+ app.setup.showFlux = false;
319
+ }
320
+ };
321
+ configs[key].cancel = { type: 'button', name: 'Ignore Changes', click: function() {
322
+ app.setup.showFlux = false;
323
+ }
324
+ };
325
+
326
+ configs[key].test_event = { type: 'json', value: '{}', default: '{}' };
327
+
328
+ configs[key].run_test = { type: 'button', name: 'Test Run This Flux', click: function(c, hey) {
329
+ var previousName = hey.run_test.name;
330
+ Vue.set(hey.run_test, 'name', 'Loading');
250
331
  app.results = [];
251
- Vue.set(app.results, 'loading', true);
252
- axios.post('/run', { config: c, setup: thingToData(app.setup) })
332
+ Vue.set(app.results, 'errorMessage', '');
333
+ var the_setup = thingToData(app.setup);
334
+ the_setup.event = c.test_event;
335
+ axios.post('/run', { config: c, setup: the_setup })
253
336
  .then(function(r){
254
- Vue.set(app.results, 'loading', false);
337
+ var index = 1;
255
338
  for (var key in r.data.result)
256
- app.results.push({darren: { type:'jsonview', value: r.data.result[key], view: 'thin' }});
339
+ {
340
+ var result = {};
341
+ result['event_' + index] = { type: 'jsonview', label: 'Event ' + index + ' of ' + r.data.result.length, value: r.data.result[key], view: 'thin' };
342
+ app.results.push(result);
343
+ index += 1;
344
+ }
345
+ }).catch(function(r){
346
+ console.log(r);
347
+ Vue.set(app.results, 'errorMessage', 'This app failed while trying to execute your flux.');
348
+ }).then(function(){
349
+ Vue.set(hey.run_test, 'name', previousName);
257
350
  });
258
351
  } };
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
352
  }
282
353
 
283
- var loadThisFlux = function(flux, setup, config)
354
+ var loadThisFlux = function(args)
284
355
  {
356
+ var flux = args.flux;
357
+ var setup = args.setup;
358
+ var config = args.config;
359
+
285
360
  Vue.set(setup.id, 'value', flux.id);
286
361
  Vue.set(setup.name, 'value', flux.name);
287
362
  Vue.set(setup.flux, 'value', flux.flux);
288
- Vue.set(setup.parent, 'value', flux.parent);
363
+ Vue.set(setup.parents, 'value', flux.parents);
289
364
 
290
365
  var applicable_config = configs[flux.flux];
291
366
  for(var key in applicable_config)
@@ -294,12 +369,15 @@ module Mushy
294
369
  else
295
370
  Vue.set(applicable_config[key], 'value', applicable_config[key].default);
296
371
 
372
+ if (applicable_config)
373
+ Vue.set(applicable_config.test_event, 'value', '{}');
297
374
 
298
375
  options = flowdata.fluxs.filter(function(x){ return x.id != flux.id });
299
376
  options.unshift( { id: '', name: '' } );
300
- setup.parent.options = options;
377
+ setup.parents.options = options;
301
378
 
302
379
  Vue.set(setup, 'showFlux', true);
380
+ app.results = [];
303
381
  };
304
382
 
305
383
  function uuidv4() {
@@ -315,15 +393,20 @@ module Mushy
315
393
  startNew: function(x) {
316
394
  flux = {
317
395
  id: uuidv4(),
318
- name: 'you',
396
+ name: '',
397
+ parents: [],
319
398
  config: {}
320
399
  };
321
- loadThisFlux(flux, x.setup, x.configs);
400
+ loadThisFlux({ flux: flux, setup: x.setup, configs: x.configs });
322
401
  },
323
- edit: function(x) {
402
+ editFlux: function(x) {
324
403
  var flux = x.flux;
325
404
 
326
- loadThisFlux(x.flux, x.setup, x.configs);
405
+ loadThisFlux({ flux: x.flux, setup: x.setup, configs: x.configs });
406
+ },
407
+ deleteFlux: function(x) {
408
+ var set = x.flow.fluxs.filter( function(v){ return v.id != x.flux.id } );
409
+ Vue.set(x.flow, 'fluxs', set);
327
410
  },
328
411
  saveFlow: function(input)
329
412
  {
@@ -331,11 +414,15 @@ module Mushy
331
414
  var flow = input.flow;
332
415
  axios.post('/save', flow)
333
416
  .then(function(result){
334
- Vue.set(setup, 'show', false);
417
+ Vue.set(setup, 'showFlux', false);
335
418
  });
336
419
  },
337
420
  configs: configs,
338
421
  setup: setup,
422
+ flux_name_for: function(ids, fluxes) {
423
+ var fluxs = fluxes.filter(function(x){ return ids.includes(x.id) });
424
+ return fluxs.map(function(x){ return x.name }).join(', ');
425
+ },
339
426
  results: [],
340
427
  }
341
428
  });
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,26 +49,29 @@ 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',
74
+ shrink: true,
63
75
  value: '',
64
76
  },
65
77
  },
@@ -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.6'
7
+ s.version = '0.2.0'
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.6
4
+ version: 0.2.0
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