You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by db...@apache.org on 2016/10/27 19:04:14 UTC
[01/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Repository: ambari
Updated Branches:
refs/heads/branch-2.5 7306e0b2f -> 7c7412ed4
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fs-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fs-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fs-action-info-test.js
new file mode 100644
index 0000000..73ccced
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fs-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('fs-action-info', 'Integration | Component | fs action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{fs-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#fs-action-info}}
+ template block text
+ {{/fs-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fsaction-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fsaction-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fsaction-info-test.js
new file mode 100644
index 0000000..2526fcf
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/fsaction-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('fsaction-info', 'Integration | Component | fsaction info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{fsaction-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#fsaction-info}}
+ template block text
+ {{/fsaction-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive-action-info-test.js
new file mode 100644
index 0000000..849408a
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('hive-action-info', 'Integration | Component | hive action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{hive-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#hive-action-info}}
+ template block text
+ {{/hive-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive2-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive2-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive2-action-info-test.js
new file mode 100644
index 0000000..d21436d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/hive2-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('hive2-action-info', 'Integration | Component | hive2 action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{hive2-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#hive2-action-info}}
+ template block text
+ {{/hive2-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/info-header-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/info-header-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/info-header-test.js
new file mode 100644
index 0000000..b91efc8
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/info-header-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('info-header', 'Integration | Component | info header', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{info-header}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#info-header}}
+ template block text
+ {{/info-header}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/instance-list-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/instance-list-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/instance-list-config-test.js
new file mode 100644
index 0000000..785b796
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/instance-list-config-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('instance-list-config', 'Integration | Component | instance list config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{instance-list-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#instance-list-config}}
+ template block text
+ {{/instance-list-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/java-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/java-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/java-action-info-test.js
new file mode 100644
index 0000000..9109977
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/java-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('java-action-info', 'Integration | Component | java action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{java-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#java-action-info}}
+ template block text
+ {{/java-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/job-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/job-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/job-config-test.js
new file mode 100644
index 0000000..052557d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/job-config-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('job-config', 'Integration | Component | job config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{job-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#job-config}}
+ template block text
+ {{/job-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-config-test.js
new file mode 100644
index 0000000..5c55922
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-config-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('killnode-config', 'Integration | Component | killnode config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{killnode-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#killnode-config}}
+ template block text
+ {{/killnode-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-manager-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-manager-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-manager-test.js
new file mode 100644
index 0000000..2691d60
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/killnode-manager-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('killnode-manager', 'Integration | Component | killnode manager', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{killnode-manager}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#killnode-manager}}
+ template block text
+ {{/killnode-manager}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/map-reduce-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/map-reduce-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/map-reduce-action-info-test.js
new file mode 100644
index 0000000..37b44b4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/map-reduce-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('map-reduce-action-info', 'Integration | Component | map reduce action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{map-reduce-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#map-reduce-action-info}}
+ template block text
+ {{/map-reduce-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/name-value-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/name-value-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/name-value-info-test.js
new file mode 100644
index 0000000..faf4987
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/name-value-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('name-value-info', 'Integration | Component | name value info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{name-value-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#name-value-info}}
+ template block text
+ {{/name-value-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/pig-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/pig-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/pig-action-info-test.js
new file mode 100644
index 0000000..60056de
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/pig-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('pig-action-info', 'Integration | Component | pig action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{pig-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#pig-action-info}}
+ template block text
+ {{/pig-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/prepare-config-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/prepare-config-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/prepare-config-info-test.js
new file mode 100644
index 0000000..abf9610
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/prepare-config-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('prepare-config-info', 'Integration | Component | prepare config info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{prepare-config-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#prepare-config-info}}
+ template block text
+ {{/prepare-config-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/preview-dialog-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/preview-dialog-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/preview-dialog-test.js
new file mode 100644
index 0000000..e1d3775
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/preview-dialog-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('preview-dialog', 'Integration | Component | preview dialog', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{preview-dialog}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#preview-dialog}}
+ template block text
+ {{/preview-dialog}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/property-value-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/property-value-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/property-value-config-test.js
new file mode 100644
index 0000000..55b5cb9
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/property-value-config-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('property-value-config', 'Integration | Component | property value config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{property-value-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#property-value-config}}
+ template block text
+ {{/property-value-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/save-wf-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/save-wf-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/save-wf-test.js
new file mode 100644
index 0000000..4555056
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/save-wf-test.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('save-wf', 'Integration | Component | save wf', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{save-wf}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#save-wf}}
+ template block text
+ {{/save-wf}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/shell-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/shell-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/shell-action-info-test.js
new file mode 100644
index 0000000..43958c4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/shell-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('shell-action-info', 'Integration | Component | shell action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{shell-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#shell-action-info}}
+ template block text
+ {{/shell-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/spark-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/spark-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/spark-action-info-test.js
new file mode 100644
index 0000000..e5b8995
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/spark-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('spark-action-info', 'Integration | Component | spark action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{spark-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#spark-action-info}}
+ template block text
+ {{/spark-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sqoop-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sqoop-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sqoop-action-info-test.js
new file mode 100644
index 0000000..e4f0994
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sqoop-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('sqoop-action-info', 'Integration | Component | sqoop action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{sqoop-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#sqoop-action-info}}
+ template block text
+ {{/sqoop-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/ssh-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/ssh-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/ssh-action-info-test.js
new file mode 100644
index 0000000..c9dcb00
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/ssh-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('ssh-action-info', 'Integration | Component | ssh action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{ssh-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#ssh-action-info}}
+ template block text
+ {{/ssh-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sub-workflow-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sub-workflow-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sub-workflow-action-info-test.js
new file mode 100644
index 0000000..576aaf8
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/sub-workflow-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('sub-workflow-action-info', 'Integration | Component | sub workflow action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{sub-workflow-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#sub-workflow-action-info}}
+ template block text
+ {{/sub-workflow-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workflow-clipboard-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workflow-clipboard-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workflow-clipboard-test.js
new file mode 100644
index 0000000..2420a2a
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workflow-clipboard-test.js
@@ -0,0 +1,29 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('service:workflow-clipboard', 'Unit | Service | workflow clipboard', {
+ // Specify the other units that are required for this test.
+ // needs: ['service:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let service = this.subject();
+ assert.ok(service);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workspace-manager-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workspace-manager-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workspace-manager-test.js
new file mode 100644
index 0000000..e3083bb
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/services/workspace-manager-test.js
@@ -0,0 +1,29 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('service:workspace-manager', 'Unit | Service | workspace manager', {
+ // Specify the other units that are required for this test.
+ // needs: ['service:foo']
+});
+
+// Replace this with your real tests.
+test('it exists', function(assert) {
+ let service = this.subject();
+ assert.ok(service);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/decission-node-validator-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/decission-node-validator-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/decission-node-validator-test.js
new file mode 100644
index 0000000..3a9c059
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/decission-node-validator-test.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:decission-node-validator', 'Unit | Validator | decission-node-validator', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-data-node-name-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-data-node-name-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-data-node-name-test.js
new file mode 100644
index 0000000..07d73b0
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-data-node-name-test.js
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:duplicate-data-node-name', 'Unit | Validator | duplicate-data-node-name', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-flattened-node-name-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-flattened-node-name-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-flattened-node-name-test.js
new file mode 100644
index 0000000..9c40325
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-flattened-node-name-test.js
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:duplicate-flattened-node-name', 'Unit | Validator | duplicate-flattened-node-name', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-kill-node-name-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-kill-node-name-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-kill-node-name-test.js
new file mode 100644
index 0000000..dd12d63
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/duplicate-kill-node-name-test.js
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:duplicate-kill-node-name', 'Unit | Validator | duplicate-kill-node-name', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/fs-action-validator-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/fs-action-validator-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/fs-action-validator-test.js
new file mode 100644
index 0000000..3a441ac
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/fs-action-validator-test.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:fs-action-validator', 'Unit | Validator | fs-action-validator', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/job-params-validator-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/job-params-validator-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/job-params-validator-test.js
new file mode 100644
index 0000000..e757c56
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/job-params-validator-test.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:job-params-validator', 'Unit | Validator | job-params-validator', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/operand-length-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/operand-length-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/operand-length-test.js
new file mode 100644
index 0000000..74195f4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/operand-length-test.js
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:operand-length', 'Unit | Validator | operand-length', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/unique-name-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/unique-name-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/unique-name-test.js
new file mode 100644
index 0000000..96e494f
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/unit/validators/unique-name-test.js
@@ -0,0 +1,27 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleFor, test } from 'ember-qunit';
+
+moduleFor('validator:unique-name', 'Unit | Validator | unique-name', {
+ needs: ['validator:messages']
+});
+
+test('it works', function(assert) {
+ var validator = this.subject();
+ assert.ok(validator);
+});
[04/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/dataset-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/dataset-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/dataset-config.hbs
new file mode 100644
index 0000000..e07a58c
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/dataset-config.hbs
@@ -0,0 +1,70 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="well">
+ <div class="form-group">
+ <label for="" class="control-label col-xs-2">Name<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ {{input type="text" class="form-control" name="dataset-name" value=dataset.name placeholder="Dataset Name"}}
+ {{field-error model=this field='dataset.name' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ <div class="form-group">
+ <label for="" class="control-label col-xs-2">URI Template<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ {{input type="text" class="form-control" name="uri-template" value=dataset.uriTemplate placeholder="baseFsURI/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}"}}
+ {{field-error model=this field='dataset.uriTemplate' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="control-label col-xs-2">Frequency<span class="requiredField"> *</span></label>
+ <div class="col-xs-2">
+ <select class="form-control" name="frequency-type" title="Frequency type" onchange={{action (mut dataset.frequency.type) value="target.value"}}>
+ {{#each timeUnitOptions as |timeUnit|}}
+ <option value={{timeUnit.value}} selected={{eq timeUnit.value dataset.frequency.type}}>{{timeUnit.displayName}}</option>
+ {{/each}}
+ </select>
+ {{#field-error model=this field='dataset.frequency.type' showErrorMessage=showErrorMessage}}{{/field-error}}
+ </div>
+ <div class="col-xs-3">
+ {{input class="form-control" type="text" value=dataset.frequency.value placeholder="frequency" title="Periodic intervals at which datasets that are produced, and coordinator applications are scheduled to run"}}
+ {{field-error model=this field='dataset.frequency.value' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ {{#date-with-expr required=true inputName="initialInstance" label="Initial Instance" inputPlaceholder="Initial Instance" dateField=dataset.initialInstance register="registerChild" deregister="deregisterChild"}}{{/date-with-expr}}
+ <div class="form-group">
+ <label for="" class="control-label col-xs-2">Time Zone<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ <select onchange={{action (mut dataset.timezone) value="target.value"}} name="select-input" class="form-control" data-show-icon="true">
+ {{#each timezoneList as |timezone index|}}
+ <option value={{timezone.value}} selected={{eq timezone.value dataset.timezone}}>{{timezone.displayName}}</option>
+ {{/each}}
+ </select>
+ {{field-error model=this field='dataset.timezone' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="col-xs-7 pull-right">
+ <button id="dataset-add-btn" {{action 'cancelDatasetOperation'}} type="button" class="btn btn-default">Cancel</button>
+ {{#if createMode}}
+ <button id="dataset-add-btn" {{action 'addDataset'}} type="button" class="btn btn-primary">Save</button>
+ {{else}}
+ <button id="dataset-update-btn" {{action 'updateDataset'}} type="button" class="btn btn-primary"> Update </button>
+ {{/if}}
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/date-with-expr.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/date-with-expr.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/date-with-expr.hbs
new file mode 100644
index 0000000..4c86f3d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/date-with-expr.hbs
@@ -0,0 +1,41 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="form-group">
+ <label for="" class="control-label col-xs-2">{{label}}
+ {{#if required}}
+ <span class="requiredField"> *</span>
+ {{/if}}
+ </label>
+ <div class="col-xs-7">
+ <div class="input-group">
+ <div class="input-group-btn">
+ <button onclick={{action (mut dateField.type) "date"}} type="button" class="btn btn-default {{if (eq dateField.type 'date') 'btn-primary' ''}} scope-btn">
+ Date
+ </button>
+ <button onclick={{action (mut dateField.type) "expr"}} type="button" class="btn btn-default {{if (eq dateField.type 'expr') 'btn-primary' ''}} scope-btn">
+ Expression
+ </button>
+ </div>
+ {{input type="text" class="form-control" name=inputName value=dateField.displayValue placeholder=inputPlaceholder}}
+ </div>
+ {{#if required}}
+ {{field-error model=this field='dateField.displayValue' showErrorMessage=showErrorMessage}}
+ {{/if}}
+ </div>
+ {{yield}}
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-add-branch.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-add-branch.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-add-branch.hbs
index 19447dd..5670879 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-add-branch.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-add-branch.hbs
@@ -31,7 +31,7 @@ type="button" data-html="true">
<label for="inputPassword" class="control-label col-xs-4">Condition<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" value=condition}}
- {{field-error error=errors.condition}}
+ {{field-error model=this field='condition' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
@@ -46,7 +46,7 @@ type="button" data-html="true">
<option value={{node.id}} selected={{eq node.name currentNode.errorNode.name}}>{{node.name}}</option>
{{/each}}
</select>
- {{field-error error=errors.targetNode}}
+ {{field-error model=this field='targetNode' showErrorMessage=showErrorMessage}}
</div>
</div>
</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-config.hbs
index 342653f..cb7ff46 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-config.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/decision-config.hbs
@@ -16,7 +16,7 @@
* limitations under the License.
}}
<div class="decisionNodeError">
- {{#field-error error=errors.actionModel}}{{/field-error}}
+ {{field-error model=this field='actionModel' showErrorMessage=showErrorMessage}}
</div>
<table id="decision-properties-table" class="table decision-properties-table listing table-hover table-bordered" cellspacing="0">
<thead>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
new file mode 100644
index 0000000..b775302
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/designer-workspace.hbs
@@ -0,0 +1,106 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="main">
+ <nav class="navbar navbar-default mb0">
+ <div class="container-fluid">
+ <div class="row">
+ <div class="col-sm-4">
+ <div class="navbar-brand">
+ <label for="">Workflow Designer</label>
+ </div>
+ </div>
+ <div class="col-sm-8">
+ <div class="text-right pull-right paddingtop7">
+ <div class="btn-group btn-group" role="group" aria-label="buttons">
+ <button id="wfs_btn" {{action 'show' 'wf'}} type="button" class="btn btn-default">
+ <i class="fa fa-sitemap marginright5"></i>
+ {{#if hasMultitabSupport}}
+ New Workflow
+ {{else}}
+ Workflow
+ {{/if}}
+ </button>
+ <button id="coords_btn" {{action 'show' 'coord'}} type="button" class="btn btn-default">
+ <i class="fa fa-history marginright5"></i>
+ {{#if hasMultitabSupport}}
+ New Coordinator
+ {{else}}
+ Coordinator
+ {{/if}}
+ </button>
+ <button id="bundles_btn" {{action 'show' 'bundle'}} type="button" class="btn btn-default">
+ <i class="fa fa-cubes marginright5"></i>
+ {{#if hasMultitabSupport}}
+ New Bundle
+ {{else}}
+ Bundle
+ {{/if}}
+ </button>
+ {{#link-to 'dashboard' class="backto-dashboard btn btn-default" title="Workflow Dashboard"}}
+ <i class="fa fa-th marginright5"></i>Dashboard
+ {{/link-to}}
+ </div>
+ {{help-icon}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </nav>
+ <ul class="nav nav-tabs tab-panel-heading">
+ {{#each tabs as |tab index|}}
+ <li class="{{if (eq index currentIndex) 'active'}}" title="{{tab.filePath}}">
+ <a href="#{{tab.id}}" data-toggle="tab" {{action 'interceptShow' tab}}>
+ {{#if (eq tab.type 'wf')}}
+ <i class="fa fa-sitemap marginright5"></i>
+ {{else if (eq tab.type 'coord')}}
+ <i class="fa fa-history marginright5"></i>
+ {{else if (eq tab.type 'bundle')}}
+ <i class="fa fa-cubes marginright5"></i>
+ {{/if}}
+ {{tab.name}}
+ <span class="closeTab" {{action "closeTab" index bubbles=false }}>x</span>
+ </a>
+ </li>
+ {{/each}}
+ </ul>
+ <div class="tab-content">
+ {{#each tabs as |tab index|}}
+ <div class="tab-pane {{if (eq index currentIndex) 'active'}}" id="{{tab.id}}">
+ {{#if (eq tab.type 'wf')}}
+ {{flow-designer xmlAppPath=tab.path register="register" openTab="openTab" changeTabName="changeTabName" changeFilePath="changeFilePath" tabInfo=tab}}
+ {{else if (eq tab.type 'coord')}}
+ {{coord-config xmlAppPath=tab.path register="register" openTab="openTab" changeTabName="changeTabName" changeFilePath="changeFilePath" tabInfo=tab}}
+ {{else if (eq tab.type 'bundle')}}
+ {{bundle-config register="register" openTab="openTab" changeTabName="changeTabName" changeFilePath="changeFilePath" tabInfo=tab}}
+ {{else}}
+ {{spin-spinner lines=7 length=3 width=3 radius=3 top=-10 left=150}}
+ {{/if}}
+ </div>
+ {{/each}}
+ </div>
+</div>
+<!--
+ {{#if (eq type 'wf')}}
+ {{flow-designer xmlAppPath=appPath isNew=isNew}}
+ {{else if (eq type 'coord')}}
+ {{coord-config}}
+ {{else if (eq type 'bundle')}}
+ {{bundle-config}}
+ {{else}}
+ {{spin-spinner lines=7 length=3 width=3 radius=3 top=-10 left=150}}
+ {{/if}} -->
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/distcp-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/distcp-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/distcp-action-info.hbs
new file mode 100644
index 0000000..c7de5e4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/distcp-action-info.hbs
@@ -0,0 +1,35 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager : </b><br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.javaOpts}}<li class="list-group-item"><b>Java Opts : </b><br/>{{hoveredAction.javaOpts}}</li>{{/if}}
+ {{#if hoveredAction.args}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action-info.hbs
new file mode 100644
index 0000000..a8c5343
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action-info.hbs
@@ -0,0 +1,28 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.to}}<li class="list-group-item"><b>To : </b><br/>{{hoveredAction.to}}</li>{{/if}}
+ {{#if hoveredAction.cc}}<li class="list-group-item"><b>Cc : </b><br/>{{hoveredAction.cc}} </li>{{/if}}
+ {{#if hoveredAction.bcc}}<li class="list-group-item"><b>Bcc : </b><br/>{{hoveredAction.bcc}} </li>{{/if}}
+ {{#if hoveredAction.subject}}<li class="list-group-item"><b>Subject : </b><br/>{{hoveredAction.subject}} </li>{{/if}}
+ {{#if hoveredAction.body}}<li class="list-group-item"><b>Body : </b><br/>{{hoveredAction.body}} </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action.hbs
index b9680a1..7622eb7 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/email-action.hbs
@@ -22,14 +22,14 @@
<label for="inputEmail" class="control-label col-xs-2">To<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="to" value=actionModel.to placeholder="Email to" title="list of comma seperated email id's"}}
- {{field-error error=errors.actionModel.to}}
+ {{field-error model=this field='actionModel.to' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
<label for="inputEmail" class="control-label col-xs-2">Cc </label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="cc" value=actionModel.cc placeholder="Cc To" title="list of comma seperated email id's"}}
- {{field-error error=errors.actionModel.cc}}
+ {{field-error model=this field='actionModel.cc' showErrorMessage=showErrorMessage}}
</div>
</div>
@@ -37,7 +37,7 @@
<label for="inputEmail" class="control-label col-xs-2">Bcc </label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="bcc" value=actionModel.bcc placeholder="Bcc To" title="list of comma seperated email id's"}}
- {{field-error error=errors.actionModel.bcc}}
+ {{field-error model=this field='actionModel.bcc' showErrorMessage=showErrorMessage}}
</div>
</div>
@@ -45,7 +45,7 @@
<label for="inputEmail" class="control-label col-xs-2">Subject<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="subject" value=actionModel.subject placeholder="Subject"}}
- {{field-error error=errors.actionModel.subject}}
+ {{field-error model=this field='actionModel.subject' showErrorMessage=showErrorMessage}}
</div>
</div>
@@ -53,7 +53,7 @@
<label for="inputEmail" class="control-label col-xs-2">Body<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{textarea class="form-control" name="body" value=actionModel.body placeholder="Body"}}
- {{field-error error=errors.actionModel.body}}
+ {{field-error model=this field='actionModel.body' showErrorMessage=showErrorMessage}}
</div>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/field-error.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/field-error.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/field-error.hbs
index 8f4d8dc..f0282bf 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/field-error.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/field-error.hbs
@@ -16,6 +16,9 @@
* limitations under the License.
}}
{{yield}}
+{{#if (or (and showErrorMessage (v-get model field 'isInvalid')) (and (v-get model field 'isInvalid')(v-get model field 'isDirty')))}}
+ <label class="control-label text-danger"> {{v-get model field 'message'}}</label>
+{{/if}}
{{#if errorMessage}}
<label class="control-label text-danger">{{errorMessage}}</label>
{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
index 71eec96..c8f0f0e 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/flow-designer.hbs
@@ -16,87 +16,138 @@
* limitations under the License.
}}
<div class="main">
- <nav class="navbar navbar-default mb0">
- <div class="container-fluid">
+ <nav class="navbar navbar-default mb0 borderTopNone">
+ <div class="container-fluid container-custom">
<div class="navbar-header">
- <div class="navbar-brand">
- <div class="padding0">
- Workflow Designer
+ <div class="form-inline col-xs-4 paddingtop8">
+ <div class="form-group">
+ <label for="wf_title">Name</label>
+ {{input class="form-control job-title" type="text" name="wf_title" value=workflow.name title="Workflow Name" placeholder="Workflow Name"}}
</div>
</div>
- <div class="padding0">
- {{input class="form-control" type="text" id="wf_title" value=workflow.name title="Workflow Name" placeholder="Workflow Name"}}
- </div>
{{#if workflowFilePath}}
<div class="wf-path padding20" title={{workflowFilePath}}>
Path:{{ workflowFilePath}}
</div>
{{/if}}
- <div class="navbar-brand pull-right paddingtop10">
- <div class="btn-group" role="group" aria-label="...">
- <button type="button" class="btn btn-default" data-toggle="modal" data-target="#ConfirmDialog" title="New Workflow" {{action "conirmCreatingNewWorkflow"}}>
- <i class="fa fa-file"> New</i>
- </button>
- <button type="button" class="btn btn-default" title="Import workflow" {{action "showFileBrowser"}}>
- <i class="fa fa-download"> Import</i>
- </button>
- <button id="import-workflow-test" type="button" class="btn btn-default hide" title="Import workflow Test" {{action "importWorkflowTest"}}>
- <i class="fa fa-download"></i>
- </button>
- <button type="button" class="btn btn-primary" title="Submit workflow" {{action "submitWorkflow"}}>
- <i class="fa fa-upload"> Submit</i>
- </button>
- {{#link-to 'dashboard' class="backto-dashboard" }}
- <button type="button" class="btn btn-default" title="Workflow Dashboard">
- <i class="fa fa-th"> Dashboard</i>
- </button>
- {{/link-to}}
- </div>
+ <div class="navbar-brand pull-right paddingtop8 col-xs-18">
+ <button type="button" class="btn btn-default" title="Import workflow" {{action "showFileBrowser"}}>
+ <i class="fa fa-download marginright5"></i>Import
+ </button>
+ <button id="import-workflow-test" type="button" class="btn btn-default hide" title="Import workflow Test" {{action "importWorkflowTest"}}>
+ <i class="fa fa-download"></i>
+ </button>
<div class="btn-group">
<div class="dropdown">
- <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">Settings
+ <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown"><i class="fa fa-refresh marginright5"></i>Reset
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li>
- <a href="javascript:void(0)" title="Global Configurations" {{action "showWorkflowGlobalProps"}}>
- Global Configurations
- </a>
+ <a data-toggle="modal" data-target="#ConfirmDialog" title="Reset Workflow" {{action "conirmCreatingNewWorkflow"}}>
+ Reset Workflow
+ </a>
</li>
- <li><a href="javascript:void(0)" title="Workflow Credentials Configuration" {{action "showCredentials" true}}>
- Workflow Credentials
- </a></li>
- <li><a href="javascript:void(0)" title="SLA for Workflow" {{action "showWorkflowSla" true}}>
- SLA for Workflow
- </a>
+ {{#if useCytoscape}}
+ <li>
+ <a title="Reset Layout" {{action "resetLayout"}}>
+ Reset Layout
+ </a>
</li>
- <li><a href="javascript:void(0)" title="Workflow Parameters Configuration" {{action "showParameterSettings" true}}>
- Workflow Parameters
- </a></li>
- <li><a href="javascript:void(0)" title="Workflow and Action Versions" {{action "showVersionSettings" true}}>
- Workflow and Action Versions
- </a>
- </li>
+ {{/if}}
</ul>
</div>
</div>
<div class="btn-group">
- <button type="button" class="btn btn-default" data-toggle="modal" data-target="#kill-node-dialog" title="Create Kill Node" {{action "showCreateKillNode" true}}>
- <i class="fa fa-ban"></i>
+ <div class="btn-group">
+ <div class="dropdown">
+ <button class="btn btn-default dropdown-toggle borderRightRadiusNone" type="button" data-toggle="dropdown"><i class="fa fa-ban marginright5"></i>Kill Nodes
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu">
+ <li>
+ <a data-toggle="modal" title="Create Kill Node" {{action "showCreateKillNode" true}}>
+ Create Kill Node
+ </a>
+ <a data-toggle="modal" title="Manage Kill Nodes" {{action "showKillNodeManager" true}}>
+ Manage Kill Nodes
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div class="btn-group">
+ <div class="dropdown">
+ <button class="btn btn-default dropdown-toggle borderRadiusNone" type="button" data-toggle="dropdown"><i class="fa fa-cog marginright5"></i>Settings
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu">
+ <li>
+ <a href="javascript:void(0)" title="Global Configurations" {{action "showWorkflowGlobalProps"}}>
+ Global Configurations
+ </a>
+ </li>
+ <li><a href="javascript:void(0)" title="Workflow Credentials Configuration" {{action "showCredentials" true}}>
+ Workflow Credentials
+ </a></li>
+ <li><a href="javascript:void(0)" title="SLA for Workflow" {{action "showWorkflowSla" true}}>
+ SLA for Workflow
+ </a>
+ </li>
+ <li><a href="javascript:void(0)" title="Workflow Parameters Configuration" {{action "showingParameterSettings" true}}>
+ Workflow Parameters
+ </a></li>
+ <li><a href="javascript:void(0)" title="Workflow and Action Versions" {{action "showVersionSettings" true}}>
+ Workflow and Action Versions
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <div class="btn-group">
+ <div class="dropdown">
+ <button class="btn btn-default dropdown-toggle borderRadiusNone" type="button" data-toggle="dropdown"><i class="marginright5"></i>More
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu">
+ <li>
+ <a href="javascript:void(0)" data-toggle="modal" data-target="#previewModal" title="Preview workflow" {{action "previewWorkflow"}}>
+ <i class="fa fa-eye marginright5"></i>Preview xml
+ </a>
+ </li>
+ <li>
+ <a href="javascript:void(0)" data-toggle="modal" title="Download workflow" {{action "downloadWorkflowXml"}}>
+ <i class="fa fa-download marginright5"></i>Download xml
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ <button type="button" class="btn btn-default" title="Submit workflow" {{action "saveWorkflow"}}>
+ <i class="fa fa-floppy-o marginright5"></i>Save
+ </button>
+ <button type="button" class="btn btn-primary" title="Dry run workflow" {{action "dryRunWorkflow"}}>
+ <i class="fa fa-play marginright5"></i> Test Run
</button>
-
- <button data-toggle="modal" data-target="#previewModal" type="button" class="btn btn-default" title="Preview workflow" {{action "previewWorkflow"}}>
- <i class="fa fa-eye"></i>
+ <button type="button" class="btn btn-primary" title="Submit workflow" {{action "submitWorkflow"}}>
+ <i class="fa fa-upload marginright5"></i>Submit
</button>
</div>
- {{help-icon}}
</div>
</div>
</div>
</nav>
+ {{#if showNotificationPanel}}
+ {{component hoveredWidget hoveredAction=hoveredAction hideNotification="hideNotification"}}
+ {{/if}}
<div id="content" class="panel panel-default designer-main-panel col-xs-20">
<div class="panel-body designer-panel designer-canvas">
{{designer-errors errors=errors validationErrors=validationErrors}}
-
+ {{#if undoAvailable}}
+ <div id="alert"class="alert alert-warning" role="alert">
+ {{#if (eq undoType 'node')}}
+ <label>Node <i>{{deletedNode.name}}</i> deleted <span class="undo" {{action 'undoDelete'}}><u>Undo</u></span></label>
+ {{else}}
+ <label>Transition deleted <span class="undo" {{action 'undoDelete'}}><u>Undo</u></span></label>
+ {{/if}}
+ </div>
+ {{/if}}
{{#if isWorkflowImporting}}
<div id="loader">
<div id="alert"class="alert alert-info alert-dismissible" role="alert">
@@ -107,38 +158,94 @@
{{#unless isImportingSuccess}}
<div id="loader">
<div id="alert"class="alert alert-danger alert-dismissible" role="alert">
- There is some problem while importing.Please try again.
+ There is some problem while importing.Please try again.
+ {{#if isStackTraceAvailable}}
+ {{#if isStackTraceVisible}}
+ <a href="#" {{action "hideStackTrace"}}>Hide Log</a>
+ <div id="stackTrace">{{{stackTrace}}}</div>
+ {{/if}}
+ {{#unless isStackTraceVisible}}
+ <a href="#" {{action "showStackTrace"}}>Show Log</a>
+ {{/unless}}
+ {{/if}}
</div>
</div>
{{/unless}}
<div id="flow-designer">
{{#each flattenedNodes as |node|}}
<div class="node-wrapper">
- {{#workflow-node node=node deleteNode="deleteNode" openEditor="openEditor" addBranch="addBranch" addDecisionBranch="addDecisionBranch" onNameChange="nameChanged"}}{{/workflow-node}}
+ {{#workflow-node node=node deleteNode="deleteNode" copyNode="copyNode" openEditor="openEditor" showNotification="showNotification" hideNotification="hideNotification" addBranch="addBranch" addDecisionBranch="addDecisionBranch" onNameChange="nameChanged"}}{{/workflow-node}}
</div>
{{/each}}
- <div id="killnodes-container">
- {{#if workflow.killNodes.length}}
- <div class="">
- <label id='kill-nodes-title' class='info' for="">Kill Nodes</label>
- </div>
- {{/if}}
- {{#each workflow.killNodes as |node|}}
- {{#workflow-node positionRelative=1 node=node deleteNode="deleteNode" openEditor="openEditor" addBranch="addBranch" onNameChange="nameChanged" addNode="addNode"}}{{/workflow-node}}
+ {{#if useCytoscape}}
+ <div id="cyRenderer">
+ <div id="{{cyId}}" class="cy-panel"></div>
+ {{#each dataNodes as |dataNode|}}
+ {{#if (or (eq dataNode.data.type 'action') (eq dataNode.data.type 'decision') (eq dataNode.data.type 'fork'))}}
+ <div id="{{dataNode.data.id}}" class="">
+ {{input required pattern="([a-zA-Z_]([\-_a-zA-Z0-9])*){1,39}" name="actionName" data-toggle="tooltip" title=dataNode.name classBinding="dataNode.data.node.errors:error:editable" class="editableNode overlay_node_editor" value=dataNode.dataNodeName placeholder="Action Name"}}
+ </div>
+ {{/if}}
{{/each}}
+ <div class="overlay-node-label">asd</div>
+ <div class="overlay-transition-content">
+ <div class="decision-condition-label">
+ <div class="decision-condition-header">Condition</div>
+ <div class="decision-condition-body"></div>
+ </div>
+ <div class="overlay-transition-actions">
+ <span class="overlay-plus-icon">
+ <i class="fa fa-plus-square"></i>
+ </span>
+ <span class="overlay-trash-transition-icon">
+ <i class="fa fa-trash-o"></i>
+ </span>
+ </div>
+ </div>
+ <div class="overlay-node-actions">
+ <span class="overlay-settings-icon" title="Action settings">
+ <i class="fa fa-cog"></i>
+ </span>
+ <span class="overlay-opentab-icon" title="Open Parent Workflow">
+ <i class="fa fa-external-link"></i>
+ </span>
+ <span class="overlay-fork-icon">
+ <i class="fa fa-code-fork"></i>
+ </span>
+ <span class="overlay-trash-icon" title="Delete Node">
+ <i class="fa fa-trash-o"></i>
+ </span>
+ <span class="overlay-cut-icon" title="Cut Node">
+ <i class="fa fa-cut"></i>
+ </span>
+ <span class="overlay-copy-icon" title="Copy Node">
+ <i class="fa fa-copy"></i>
+ </span>
+ <span class="overlay-paste-icon" title="Replace Node from Clipboard">
+ <i class="fa fa-paste"></i>
+ </span>
+ </div>
+ {{decision-add-branch node=node registerAddBranchAction="registerAddBranchAction" addDecisionBranch="addDecisionBranch" workflow=workflow}}
</div>
+ {{#if cyOverflow.overflown}}
+ <div class="cyScrollMsg"><i class="fa fa-ellipsis-h cyScrollMsgContent" title="Use the pan tool or drag on canvas to see more" aria-hidden="true"></i></div>
+ {{/if}}
+ {{/if}}
</div>
<div id="workflow-actions" class="hidden">
- {{workflow-actions element=popOverElement addNode="addNode"}}
+ {{workflow-actions element=popOverElement addNode="addNode" pasteNode="pasteNode" clipboard=clipboard}}
</div>
</div>
</div>
</div>
{{#if showActionEditor}}
- {{workflow-action-editor actionType=currentAction closeActionEditor="closeActionEditor" addKillNode="addKillNode" actionModel=currentNode.domain nodeType=currentNode.type currentNode=currentNode killNodes=workflow.killNodes credentials=workflow.credentials}}
+ {{workflow-action-editor actionType=currentAction closeActionEditor="closeActionEditor" setNodeTransitions="setNodeTransitions" actionModel=currentNode.domain nodeType=currentNode.type currentNode=currentNode killNodes=workflow.killNodes credentials=workflow.credentials}}
+{{/if}}
+{{#if showingSaveWorkflow}}
+ {{save-wf type='wf' closeJobConfigs="closeWorkflowSubmitConfigs" jobFilePath=workflowFilePath openFileBrowser="openFileBrowser" closeFileBrowser="closeFileBrowser" jobConfigs=workflowSubmitConfigs setFilePath="setFilePath" isDryrun=dryrun}}
{{/if}}
{{#if showingWorkflowConfigProps}}
- {{workflow-config closeWorkflowSubmitConfigs="closeWorkflowSubmitConfigs" workflowFilePath=workflowFilePath openFileBrowser="openFileBrowser" closeFileBrowser="closeFileBrowser" workflowSubmitConfigs=workflowSubmitConfigs}}
+ {{job-config type='wf' closeJobConfigs="closeWorkflowSubmitConfigs" jobFilePath=workflowFilePath openFileBrowser="openFileBrowser" closeFileBrowser="closeFileBrowser" jobConfigs=workflowSubmitConfigs isDryrun=dryrun}}
{{/if}}
{{#if showGlobalConfig}}
{{#global-config closeGlobalConfig="closeWorkflowGlobalProps" saveGlobalConfig="saveGlobalConfig" actionModel=globalConfig}}{{/global-config}}
@@ -147,43 +254,12 @@
{{hdfs-browser closeFileBrowser="closeFileBrowser" selectFileCallback=selectFileCallback filePath=workflowFilePath}}
{{/if}}
{{#if showingPreview}}
- <div id="previewModal" class="modal fade" role="dialog">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal">×</button>
- <h4 class="modal-title">Workflow Xml Preview</h4>
- </div>
- <div class="modal-body">
-
- <pre class="preview-xml">{{previewXml}}</pre>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
- </div>
- </div>
- </div>
- </div>
+ {{#preview-dialog title="Workflow XML Preview" previewXml=previewXml}}{{/preview-dialog}}
{{/if}}
-
{{#if showingConfirmationNewWorkflow}}
- <div id="ConfirmDialog" class="modal fade" role="dialog">
- <div class="modal-dialog">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal">×</button>
- <h4 class="modal-title">Confirm create new workflow</h4>
- </div>
- <div class="modal-body">
- Any unsaved changes may be lost.Do you want to proceed creating new workflow?
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button type="button" class="btn btn-primary" {{action "createNewWorkflow"}} data-dismiss="modal">Continue</button>
- </div>
- </div>
- </div>
- </div>
+ {{#confirmation-dialog title="Confirm workflow reset"
+ confirmationMessage="Any unsaved changes may be lost. Do you want to proceed resetting the workflow ?"
+ okBtnText="Continue" cancelBtnText="Cancel" onOk="createNewWorkflow"}}{{/confirmation-dialog}}
{{/if}}
{{#if showCreateKillNode}}
<div id="kill-node-dialog" class="modal fade" role="dialog">
@@ -195,18 +271,15 @@
</div>
<div class="modal-body">
{{#if createKillnodeError}}
+ <div class="row">
+ <div class="form-group">
+ <label class="text-danger control-label col-xs-8">
+ {{createKillnodeError}}
+ </label>
+ </div>
+ </div>
+ {{/if}}
<div class="row">
- <div class="form-group">
-
- <label class="text-danger control-label col-xs-8">
- {{createKillnodeError}}
- </label>
-
- </div>
- </div>
- {{/if}}
- <div class="row">
-
<div class="form-group" id="killNodeName">
<label class="control-label col-xs-3"> Kill node name</label>
<div class="col-xs-7">
@@ -241,5 +314,8 @@
{{#workflow-credentials showCredentials="showCredentials" workflowCredentials=workflow.credentials}}{{/workflow-credentials}}
{{/if}}
{{#if showParameterSettings}}
- {{#workflow-parameters closeWorkFlowParam="closeWorkFlowParam" saveWorkFlowParam="saveWorkFlowParam" parameters=parameters}}{{/workflow-parameters}}
+ {{#workflow-parameters type='wf' closeWorkFlowParam="closeWorkFlowParam" saveWorkFlowParam="saveWorkFlowParam" parameters=parameters}}{{/workflow-parameters}}
+{{/if}}
+{{#if showKillNodeManager}}
+ {{#killnode-manager killNodes=workflow.killNodes killNode=killNode createKillnodeError=createKillnodeError createKillNode="createKillNode" deleteNode="deleteNode" addKillNodeMode=addKillNodeMode editMode=editMode closeKillNodeManager="closeKillNodeManager"}}{{/killnode-manager}}
{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action-info.hbs
new file mode 100644
index 0000000..2f06e29
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action-info.hbs
@@ -0,0 +1,33 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.fsOps}}<li class="list-group-item"><b>File Operations : </b>
+ {{#fsaction-info action=hoveredAction}}{{/fsaction-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action.hbs
index ef86a50..97f88fa 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fs-action.hbs
@@ -18,8 +18,7 @@
<div class="panel panel-default">
<div class="panel-heading">General</div>
<div class="panel-body">
- {{#field-error error=errors.actionModel}}{{/field-error}}
-
+ {{field-error model=this field='actionModel.fsOps' showErrorMessage=showErrorMessage}}
{{#prepare-config-fs fsOps=actionModel.fsOps openFileBrowser="openFileBrowser" register="register"}}{{/prepare-config-fs}}
{{#jobxml-config jobXml=actionModel.jobXml openFileBrowser="openFileBrowser" register="register"}}{{/jobxml-config}}
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fsaction-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fsaction-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fsaction-info.hbs
new file mode 100644
index 0000000..6fa97d9
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/fsaction-info.hbs
@@ -0,0 +1,39 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+{{#each action.fsOps as |obj|}}
+ <ul class="list-unstyled">
+ {{#if (eq obj.type "mkdir")}}
+ <li>Type is {{obj.type}} and path is {{obj.settings.path}}</li>
+ {{/if}}
+ {{#if (eq obj.type "delete")}}
+ <li>Type is {{obj.type}} and path is {{obj.settings.path}}</li>
+ {{/if}}
+ {{#if (eq obj.type "touchz")}}
+ <li>Type is {{obj.type}} and path is {{obj.settings.path}}</li>
+ {{/if}}
+ {{#if (eq obj.type "move")}}
+ <li>Type is {{obj.type}} and Source is {{obj.settings.source}} and Target is {{obj.settings.target}}</li>
+ {{/if}}
+ {{#if (eq obj.type "chmod")}}
+ <li>Type is {{obj.type}} and dirfiles is {{obj.settings.dirfiles}}, recursive is {{obj.settings.recursive}}, path is {{obj.settings.path}}, permissions are {{obj.settings.permissions}}</li>
+ {{/if}}
+ {{#if (eq obj.type "chgrp")}}
+ <li>Type is {{obj.type}} and dirfiles is {{obj.settings.dirfiles}}, recursive is {{obj.settings.recursive}}, path is {{obj.settings.path}}, group : {{obj.settings.group}}</li>
+ {{/if}}
+ </ul>
+{{/each}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hdfs-browser.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hdfs-browser.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hdfs-browser.hbs
index d3233b6..437640d 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hdfs-browser.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hdfs-browser.hbs
@@ -74,7 +74,7 @@
<label class="control-label">Selected Path</label>
</div>
<div class="col-xs-6">
- {{input id="selectedPath" class="form-control" type="text" value=selectedPath}}
+ {{input name="selectedPath" class="form-control" type="text" value=selectedPath}}
</div>
<div class="col-xs-4">
<button type="button" class="btn btn-primary" {{action "selectFile"}}>Select</button>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action-info.hbs
new file mode 100644
index 0000000..0e30972
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action-info.hbs
@@ -0,0 +1,47 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node</b> : <br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager</b> : <br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.script}}<li class="list-group-item"><b>Script</b> : <br/>{{hoveredAction.script}}</li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml</b> :
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.archives}}<li class="list-group-item"><b>Archives</b> :
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files</b> :
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.params}}<li class="list-group-item"><b>Params</b> :
+ {{#property-value-config action=hoveredAction.params}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.args}}<li class="list-group-item"><b>Args</b> :
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare</b> :
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration</b> :
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action.hbs
index dc94160..eb959c3 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive-action.hbs
@@ -36,7 +36,7 @@
<button class="btn btn-primary" type="button" {{action "openFileBrowser" "actionModel.script"}}>Browse</button>
</span>
</div>
- {{#field-error error=errors.actionModel.script}}{{/field-error}}
+ {{field-error model=this field='actionModel.script' showErrorMessage=showErrorMessage}}
</div>
</div>
{{else}}
@@ -46,7 +46,7 @@
<div class="input-group">
{{textarea class="form-control" name="query" class="query-text-area" value=actionModel.query placeholder="hive query"}}
</div>
- {{#field-error error=errors.actionModel.query}}{{/field-error}}
+ {{field-error model=this field='actionModel.query' showErrorMessage=showErrorMessage}}
</div>
</div>
{{/if}}
@@ -96,4 +96,4 @@
</div>
</div>
</div>
- {{#sla-info slaInfo=actionModel.slaInfo register="register" slaEnabled=actionModel.slaEnabled register="register"}}{{/sla-info}}
+ {{#sla-info slaInfo=actionModel.slaInfo slaEnabled=actionModel.slaEnabled register="register"}}{{/sla-info}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action-info.hbs
new file mode 100644
index 0000000..5a58b5a
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action-info.hbs
@@ -0,0 +1,49 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node :</b> <br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager :</b> <br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.script}}<li class="list-group-item"><b>Script : </b> <br/>{{hoveredAction.script}}</li>{{/if}}
+ {{#if hoveredAction.jdbc-url}}<li class="list-group-item"><b>Jdbc-url :</b> <br/>{{hoveredAction.jdbc-url}}</li>{{/if}}
+ {{#if hoveredAction.password}}<li class="list-group-item"><b>Password :</b> <br/>{{hoveredAction.password}}</li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.archives}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.params}}<li class="list-group-item"><b>Params : </b>
+ {{#property-value-config action=hoveredAction.params}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.args}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action.hbs
index c4bec81..563cca8 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/hive2-action.hbs
@@ -37,7 +37,7 @@
<button class="btn btn-primary" type="button" {{action "openFileBrowser" "actionModel.script"}}>Browse</button>
</span>
</div>
- {{#field-error error=errors.actionModel.script}}{{/field-error}}
+ {{field-error model=this field='actionModel.script' showErrorMessage=showErrorMessage}}
</div>
</div>
{{else}}
@@ -47,7 +47,7 @@
<div class="input-group">
{{textarea class="form-control" name="query" class="query-text-area" value=actionModel.query placeholder="hive query"}}
</div>
- {{#field-error error=errors.actionModel.query}}{{/field-error}}
+ {{field-error model=this field='actionModel.query' showErrorMessage=showErrorMessage}}
</div>
</div>
{{/if}}
@@ -55,7 +55,7 @@
<label class="control-label col-xs-2">jdbc-url<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" validations="required" name="jdbc-url" value=actionModel.jdbc-url placeholder="jdbc-url"}}
- {{#field-error error=errors.actionModel.jdbc-url}}{{/field-error}}
+ {{field-error model=this field='actionModel.jdbc-url' showErrorMessage=showErrorMessage}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/info-header.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/info-header.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/info-header.hbs
new file mode 100644
index 0000000..5fdd702
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/info-header.hbs
@@ -0,0 +1,18 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<b>Action Details</b><a href="#" class="pull-right" {{action "hideNotification"}}>X</a>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/instance-list-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/instance-list-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/instance-list-config.hbs
new file mode 100644
index 0000000..94f4e39
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/instance-list-config.hbs
@@ -0,0 +1,35 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div>
+ {{#each instances as |instance index|}}
+ <div class="form-group">
+ {{#date-with-expr required=true inputName="instance" label="Instance" inputPlaceholder="Instance" dateField=instance}}
+ <div class="col-xs-1">
+ <input class="form-control btn btn-danger" type="button" {{action "deleteInstance" index}} value="-">
+ </div>
+ {{/date-with-expr}}
+ </div>
+ {{/each}}
+ <div class="form-group">
+ {{#date-with-expr inputName="instance" label="Instance" inputPlaceholder="Instance" dateField=instance}}
+ <div class="col-xs-1">
+ <input class="form-control btn btn-success" type="button" value="+" {{action "addInstance"}}>
+ </div>
+ {{/date-with-expr}}
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action-info.hbs
new file mode 100644
index 0000000..e74633d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action-info.hbs
@@ -0,0 +1,52 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager : </b><br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.captureOutput}}<li class="list-group-item"><b>Capture Output : </b><br/>{{hoveredAction.captureOutput}}</li>{{/if}}
+ {{#if hoveredAction.mainClass}}<li class="list-group-item"><b>Main Class : </b><br/>{{hoveredAction.mainClass}}</li>{{/if}}
+ {{#if hoveredAction.javaOpts}}<li class="list-group-item"><b>Java Opts : </b><br/>{{hoveredAction.javaOpts}}</li>{{/if}}
+ {{#if hoveredAction.javaOpt}}<li class="list-group-item"><b>Java Opt : </b>
+ {{#property-value-config action=hoveredAction.javaOpt}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.params}}<li class="list-group-item"><b>Params : </b>
+ {{#property-value-config action=hoveredAction.params}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.args}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action.hbs
index c103bd0..bdb5261 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/java-action.hbs
@@ -22,7 +22,7 @@
<label for="inputEmail" class="control-label col-xs-2">Main class<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="main-class" value=actionModel.mainClass placeholder="Main class"}}
- {{field-error error=errors.actionModel.mainClass}}
+ {{field-error model=this field='actionModel.mainClass' showErrorMessage=showErrorMessage}}
</div>
</div>
@@ -77,7 +77,7 @@
<div class="col-xs-7">
{{input type="text" class="form-control" name="job-tracker" value=actionModel.jobTracker placeholder="Resource Manager"}}
</div>
- {{field-error error=errors.actionModel.jobTracker}}
+ {{field-error model=this field='actionModel.jobTracker' showErrorMessage=showErrorMessage}}
</div>
<div class="form-group">
<label for="inputPassword" class="control-label col-xs-2">Name node</label>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-config.hbs
new file mode 100644
index 0000000..ede8cb1
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-config.hbs
@@ -0,0 +1,126 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="modal fade" id="configureJob" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ {{#if isDryrun}}
+ <h4 class="modal-title">Dryrun {{displayName}}</h4>
+ {{else}}
+ <h4 class="modal-title">Submit {{displayName}}</h4>
+ {{/if}}
+
+ </div>
+ <div class="modal-body">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ {{#if alertType}}
+ <div id="error" class="alert alert-{{alertType}}">
+ <div>{{alertMessage}}</div>
+ <div>{{alertDetails}}</div>
+ {{#if isStackTraceAvailable}}
+ {{#if isStackTraceVisible}}
+ <a href="#" {{action "hideStackTrace"}}>Hide Log</a>
+ <div id="stackTrace">{{{stackTrace}}}</div>
+ {{/if}}
+ {{#unless isStackTraceVisible}}
+ <a href="#" {{action "showStackTrace"}}>Show Log</a>
+ {{/unless}}
+ {{/if}}
+ </div>
+ {{/if}}
+ <div class="row form-group">
+ <div class="col-xs-3">
+ <label class="control-label" for="{{type}}-path">{{displayName}} path</label><span class="requiredField"> *</span>
+ </div>
+ <div class="col-xs-8">
+ <div class="input-group">
+ {{input class="form-control" type="text" name="{{type}}-path" value=filePath}}
+ <span class="input-group-btn">
+ <button type="button" class="btn btn-primary" {{action "selectFile"}}>Browse</button>
+ </span>
+ </div>
+ {{field-error model=this field='filePath' showErrorMessage=showErrorMessage}}
+ {{input type="checkbox" checked=overwritePath}}Overwrite
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-xs-3">
+ <label class="control-label">Execution Settings</label>
+ </div>
+ <div class="col-xs-8">
+ {{#each systemConfigs as |config|}}
+ <div>
+ {{input type="checkbox" checked=config.value}}{{config.displayName}}
+ </div>
+ {{/each}}
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="jobProperties">
+ {{#if configMap.length}}
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ Job Properties
+ </div>
+ <div class="panel-body">
+ {{field-error model=this field='configMap' showErrorMessage=showErrorMessage}}
+ {{#each configMap as |prop|}}
+ <div class="row form-group">
+ <div class="col-xs-3">
+ <label class="control-label" for="{{prop}}">{{prop.name}}</label>
+ {{#if prop.isRequired}}
+ <span class="requiredField"> *</span>
+ {{/if}}
+ </div>
+ <div class="col-xs-8">
+ {{input class="form-control" type="text" value=prop.value}}
+ </div>
+ </div>
+ {{/each}}
+ </div>
+ </div>
+ {{/if}}
+ </div>
+ </div>
+ <div class="modal-footer">
+ {{#if savingInProgress}}
+ {{spin-spinner lines=10 length=10 width=5 radius=10 }}
+ <span class="pull-left">Saving {{displayName}}</span>
+ {{/if}}
+ {{#if startingInProgress}}
+ {{spin-spinner lines=8 length=5 width=10 radius=5}}
+ <span class="pull-left">Starting {{displayName}}</span>
+ {{/if}}
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ {{#if isDryrun}}
+ <button type="button" class="btn btn-primary" {{action "dryrun"}}>Test Run</button>
+ {{else}}
+ <button type="button" class="btn btn-default" {{action "dryrun"}}>Test Run</button>
+ <button type="button" class="btn btn-primary" {{action "save"}}>Submit</button>
+ {{/if}}
+
+ </div>
+ </div>
+ </div>
+</div>
+{{#if showingFileBrowser}}
+{{hdfs-browser closeFileBrowser="closeFileBrowser" selectFileCallback=selectFileCallback filePath=filePath}}
+{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-details.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-details.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-details.hbs
index 872cdbb..0a04d25 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-details.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/job-details.hbs
@@ -49,7 +49,7 @@
<li {{action 'getJobLog'}} role="presentation"><a href="#jobLog" aria-controls="jobLog" role="tab" data-toggle="tab">Log</a></li>
<li {{action 'getErrorLog'}} role="presentation"><a href="#jobErrorLog" aria-controls="jobErrorLog" role="tab" data-toggle="tab">Error Log</a></li>
<li {{action 'getAuditLog'}} role="presentation"><a href="#jobAuditLog" aria-controls="jobAuditLog" role="tab" data-toggle="tab">Audit Log</a></li>
- <li {{action 'getJobDag'}} role="presentation"><a href="#jobDag" aria-controls="jobDag" role="tab" data-toggle="tab">DAG</a></li>
+ <li {{action 'getJobDag'}} role="presentation"><a href="#jobDag" aria-controls="jobDag" role="tab" data-toggle="tab">Flow Graph</a></li>
<li role="presentation" class="pull-right">
{{#link-to 'design' (query-params appPath=model.appPath) class="backto-designer" }}
<button type="button" class="btn btn-success" title="Back" >
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-config.hbs
new file mode 100644
index 0000000..db24051
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-config.hbs
@@ -0,0 +1,67 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="panel panel-default">
+ <div class="panel-heading">
+ {{#if editMode}}
+ Edit Kill Node
+ {{else}}
+ Add Kill Node
+ {{/if}}
+ </div>
+ <div class="panel-body">
+ {{#if createKillnodeError}}
+ <div class="row">
+ <div class="form-group">
+ <label class="text-danger control-label col-xs-8">
+ {{createKillnodeError}}
+ </label>
+ </div>
+ </div>
+ {{/if}}
+ <div class="row">
+ <div class="form-group" id="killNodeName">
+ <label class="control-label col-xs-3"> Kill node name</label>
+ {{#if editMode}}
+ <label class="control-label col-xs-3">{{killNode.name}}</label>
+ {{else}}
+ <div class="col-xs-7">
+ {{input class="form-control" type="text" name="kill-node-name" value=killNode.name}}
+ </div>
+ {{/if}}
+ </div>
+ </div>
+ <div class="row padding10">
+ <div class="form-group">
+ <label class="control-label col-xs-3"> Kill message</label>
+ <div class="col-xs-7">
+ {{textarea class="form-control" rows="5" placeholder="kill node message" name="kill-node-message" value=killNode.killMessage}}
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="panel-footer clearfix">
+ <div class="pull-right">
+ {{#if editMode}}
+ <button type="button" class="btn btn-primary" {{action "updateNode"}}>Save</button>
+ {{else}}
+ <button type="button" class="btn btn-primary" {{action "createKillNode"}}>Save</button>
+ {{/if}}
+ <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-manager.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-manager.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-manager.hbs
new file mode 100644
index 0000000..9b14cfc
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/killnode-manager.hbs
@@ -0,0 +1,69 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="killnode-manager-dialog" class="modal fade" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">Kill Node Manager</h4>
+ </div>
+ <div class="modal-body">
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Kill Nodes</h4>
+ <button type="button" class="btn btn-default pull-right" {{action "addNode"}}>Add</button>
+ </div>
+ <div class="panel-body kill-nodes-list">
+ <ul class="list-group">
+ {{#each killNodes as |killNode index|}}
+ <li class="list-group-item col-xs-12">
+ <div class="col-xs-12 plr0px">
+ <label class="control-label col-xs-2">
+ Name
+ </label>
+ <div class="col-xs-10">
+ {{killNode.name}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteNode" index}}></i>
+ </span>
+ <span class="pull-right paddingright10">
+ <i class="fa fa-pencil" title="Edit" {{action "editNode" index}}></i>
+ </span>
+ </div>
+ </div>
+ <div class="col-xs-12 plr0px">
+ <label class="control-label col-xs-2">
+ Message
+ </label>
+ <div class="col-xs-10">
+ {{killNode.killMessage}}
+ </div>
+ </div>
+ </li>
+ {{/each}}
+ </ul>
+ </div>
+ </div>
+
+ {{#if (or addKillNodeMode editMode)}}
+ {{killnode-config killNode=killNode createKillnodeError=createKillnodeError editMode=editMode updateNode="updateNode" createKillNode="createKillNode"}}
+ {{/if}}
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/map-reduce-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/map-reduce-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/map-reduce-action-info.hbs
new file mode 100644
index 0000000..16d1b32
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/map-reduce-action-info.hbs
@@ -0,0 +1,41 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item"><b>The details are</b>
+ <a href="#" class="pull-right" {{action "hideNotification"}}>X</a></li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager : </b><br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.archives}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/name-value-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/name-value-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/name-value-info.hbs
new file mode 100644
index 0000000..02f2499
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/name-value-info.hbs
@@ -0,0 +1,22 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+{{#each action.configuration.property as |obj|}}
+ <ul class="list-unstyled">
+ <li>Name : {{obj.name}}, Value : {{obj.value}}</li>
+ </ul>
+{{/each}}
[08/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
index bd2944b..ed743f4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/flow-designer.js
@@ -20,17 +20,45 @@ import {Workflow} from '../domain/workflow';
import Constants from '../utils/constants';
import {WorkflowGenerator} from '../domain/workflow-xml-generator';
import {WorkflowImporter} from '../domain/workflow-importer';
+import {WorkflowJsonImporter} from '../domain/workflow-json-importer';
import {WorkflowContext} from '../domain/workflow-context';
-import {DefaultLayoutManager as LayoutManager} from '../domain/default-layout-manager';
-import EmberValidations,{ validator } from 'ember-validations';
+import {JSPlumbRenderer} from '../domain/jsplumb-flow-renderer';
+import {CytoscapeRenderer} from '../domain/cytoscape-flow-renderer';
+import {FindNodeMixin} from '../domain/findnode-mixin';
+import { validator, buildValidations } from 'ember-cp-validations';
+import WorkflowPathUtil from '../domain/workflow-path-util';
+const Validations = buildValidations({
+ 'dataNodes': { /* For Cytoscape */
+ validators: [
+ validator('duplicate-data-node-name', {
+ dependentKeys: ['dataNodes.@each.dataNodeName']
+ })
+ ]
+ },
+ 'workflow.killNodes': {
+ validators: [
+ validator('duplicate-kill-node-name', {
+ dependentKeys: ['workflow.killNodes.@each.name']
+ })
+ ]
+ },
+ 'flattenedNodes': {
+ validators: [
+ validator('duplicate-flattened-node-name', {
+ dependentKeys: ['flattenedNodes.@each.name']
+ })
+ ]
+ }
+});
-export default Ember.Component.extend(EmberValidations,{
+export default Ember.Component.extend(FindNodeMixin, Validations, {
workflowContext : WorkflowContext.create({}),
workflowTitle:"",
previewXml:"",
supportedActionTypes:["java", "hive", "pig", "sqoop", "shell", "spark", "map-reduce", "hive2", "sub-workflow", "distcp", "ssh", "FS"],
workflow:null,
+ hoveredWidget:null,/**/
showingConfirmationNewWorkflow:false,
showingWorkflowConfigProps:false,
workflowSubmitConfigs:{},
@@ -40,106 +68,118 @@ export default Ember.Component.extend(EmberValidations,{
domain:{},
showActionEditor : false,
flattenedNodes: [],
-
+ dataNodes: [], /* For cytoscape */
+ hoveredAction: null,
workflowImporter:WorkflowImporter.create({}),
- designerPlumb:null,
propertyExtractor : Ember.inject.service('property-extractor'),
+ clipboardService : Ember.inject.service('workflow-clipboard'),
+ workspaceManager : Ember.inject.service('workspace-manager'),
showGlobalConfig : false,
showParameterSettings : false,
+ showNotificationPanel : false,
globalConfig : {},
parameters : {},
clonedDomain : {},
clonedErrorNode : {},
validationErrors : [],
- layoutManager:null,
showingFileBrowser : false,
killNode : {},
isWorkflowImporting: false,
isImportingSuccess: true,
- initialize :function(){
- this.designerPlumb=jsPlumb.getInstance({});
- this.layoutManager=LayoutManager.create({});
+ shouldPersist : false,
+ useCytoscape: Constants.useCytoscape,
+ cyOverflow: {},
+ clipboard : Ember.computed.alias('clipboardService.clipboard'),
+ isStackTraceVisible: false,
+ isStackTraceAvailable: false,
+ stackTrace:"",
+ initialize : function(){
+ var id = 'cy-' + Math.ceil(Math.random() * 1000);
+ this.set('cyId', id);
+ this.sendAction('register', this.get('tabInfo'), this);
+ }.on('init'),
+ elementsInserted :function(){
+ if (this.useCytoscape){
+ this.flowRenderer=CytoscapeRenderer.create({id : this.get('cyId')});
+ }else{
+ this.flowRenderer=JSPlumbRenderer.create({});
+ }
+
this.setConentWidth();
this.set('workflow',Workflow.create({}));
if(this.get("xmlAppPath")){
- var workflowXmlPath = this.get("xmlAppPath"), relXmlPath = "", tempArr;
- if(workflowXmlPath.indexOf("://") === -1 && workflowXmlPath.indexOf(":") === -1){
- relXmlPath = workflowXmlPath;
- } else{
- tempArr = workflowXmlPath.split("//")[1].split("/");
- tempArr.splice(0, 1);
- relXmlPath = "/" + tempArr.join("/");
- if(!(relXmlPath.indexOf(".xml") === relXmlPath.length-4)) {
- if(relXmlPath.charAt(relXmlPath.length-1) !== "/"){
- relXmlPath = relXmlPath+ "/" +"workflow.xml";
- } else{
- relXmlPath = relXmlPath+"workflow.xml";
- }
- }
- }
- this.importWorkflow(relXmlPath);
+ this.showExistingWorkflow();
return;
- }else{
+ } else {
this.workflow.initialize();
this.initAndRenderWorkflow();
this.$('#wf_title').focus();
- this.restoreWorkinProgress();
+ if (Constants.autoRestoreWorkflowEnabled){
+ this.restoreWorkflow();
+ }
+ }
+ if(Ember.isBlank(this.get('workflow.name'))){
+ this.set('workflow.name', Ember.copy(this.get('tabInfo.name')));
}
- }.on('didInsertElement'),
- validations: {
- 'flattenedNodes': {
- inline : validator(function() {
- var nodeNames = new Map();
- this.get("validationErrors").clear();
- this.get('flattenedNodes').forEach((item)=>{
- Ember.set(item, "errors", false);
- if(nodeNames.get(item.name)){
- Ember.set(item, "errors", true);
- this.get("validationErrors").pushObject({node:item,message:"Node name should be unique"});
- }else{
- nodeNames.set(item.name, item);
- Ember.set(item, "errors", false);
- }
- if(this.get("supportedActionTypes").indexOf(item.actionType) === -1 && item.type === "action"){
- this.get('validationErrors').pushObject({node : item ,message : item.actionType+" is unsupported"});
- }
- var nodeErrors=item.validateCustom();
- if (nodeErrors.length>0){
- Ember.set(item, "errors", true);
- nodeErrors.forEach(function(errMsg){
- this.get("errors").pushObject({node:item,message:errMsg });
- }.bind(this));
- }
- }.bind(this));
- if(this.get('flattenedNodes').length !== nodeNames.size || this.get("errors").length>0){
- return true;
- }
- })
- },
- "workflow.killnodes": {
- inline : validator(function() {
- let killNodes = [], flag;
- if(this.get("workflow") && this.get("workflow").killNodes){
- killNodes = this.get("workflow").killNodes;
- for(let i=0; i<killNodes.length; i++){
- for(let j=0; j<killNodes.length; j++){
- if(killNodes[i].name === killNodes[j].name && i !== j){
- this.get('validationErrors').pushObject({node : killNodes[j] ,message : "Duplicate killnode"});
- flag = true;
- break;
- }
- }
- if(flag){
- break;
- }
- }
- }
- if (flag){
- return true;
+ }.on('didInsertElement'),
+ restoreWorkflow(){
+ if (!this.get("isNew")){
+ var draftWorkflow=this.getDraftWorkflow();
+ if (draftWorkflow){
+ this.resetDesigner();
+ this.set("workflow",draftWorkflow);
+ this.rerender();
+ this.doValidation();
+ }
+ }
+ },
+ observeXmlAppPath : Ember.observer('xmlAppPath', function(){
+ if(!this.get('xmlAppPath') || null === this.get('xmlAppPath')){
+ return;
+ }else{
+ this.showExistingWorkflow();
+ }
+ }),
+ observeFilePath : Ember.observer('workflowFilePath', function(){
+ if(!this.get('workflowFilePath') || null === this.get('workflowFilePath')){
+ return;
+ }else{
+ this.sendAction('changeFilePath', this.get('tabInfo'), this.get('workflowFilePath'));
+ }
+ }),
+ nameObserver : Ember.observer('workflow.name', function(){
+ if(!this.get('workflow')){
+ return;
+ }else if(this.get('workflow') && Ember.isBlank(this.get('workflow.name'))){
+ if(!this.get('clonedTabInfo')){
+ this.set('clonedTabInfo', Ember.copy(this.get('tabInfo')));
+ }
+ this.sendAction('changeTabName', this.get('tabInfo'), this.get('clonedTabInfo.name'));
+ }else{
+ this.sendAction('changeTabName', this.get('tabInfo'), this.get('workflow.name'));
+ }
+ }),
+ showParentWorkflow(type, path){
+ this.sendAction('openTab', type, path);
+ },
+ showExistingWorkflow(){
+ var workflowXmlPath = this.get("xmlAppPath"), relXmlPath = "", tempArr;
+ if(workflowXmlPath.indexOf("://") === -1 && workflowXmlPath.indexOf(":") === -1){
+ relXmlPath = workflowXmlPath;
+ } else{
+ tempArr = workflowXmlPath.split("//")[1].split("/");
+ tempArr.splice(0, 1);
+ relXmlPath = "/" + tempArr.join("/");
+ if(relXmlPath.indexOf(".xml") !== relXmlPath.length-4) {
+ if(relXmlPath.charAt(relXmlPath.length-1) !== "/"){
+ relXmlPath = relXmlPath+ "/" +"workflow.xml";
+ } else{
+ relXmlPath = relXmlPath+"workflow.xml";
}
- })
+ }
}
+ this.importWorkflow(relXmlPath);
},
setConentWidth(){
var offset = 120;
@@ -150,197 +190,101 @@ export default Ember.Component.extend(EmberValidations,{
return;
});
},
+ workflowXmlDownload(workflowXml){
+ var link = document.createElement("a");
+ link.download = "workflow.xml";
+ link.href = "data:text/xml,"+vkbeautify.xml(workflowXml);
+ link.click();
+ },
nodeRendered: function(){
- var self=this;
+ this.doValidation();
if(this.get('renderNodeTransitions')){
- var connections=[];
- var visitedNodes=[];
- this.renderTransitions(this.get("workflow").startNode,connections,visitedNodes);
- this.workflowConnections=connections;
+ this.flowRenderer.onDidUpdate(this,this.get("workflow").startNode,this.get("workflow"));
this.layout();
- this.designerPlumb.setSuspendDrawing(true);
- this.designerPlumb.batch(function(){
- connections.forEach(function(conn){
- self.designerPlumb.connect(conn);
- });
- });
- this.designerPlumb.setSuspendDrawing(false,true);
this.set('renderNodeTransitions',false);
}
+ this.resize();
this.persistWorkInProgress();
}.on('didUpdate'),
- cleanUpJsplumb:function(){
- this.get('flattenedNodes').clear();
+ resize(){
+ this.flowRenderer.resize();
+ },
+ cleanupFlowRenderer:function(){
this.set('renderNodeTransitions',false);
- this.designerPlumb.detachEveryConnection();
+ this.flowRenderer.cleanup();
}.on('willDestroyElement'),
initAndRenderWorkflow(){
- this.designerPlumb.ready(function() {
+ var panelOffset=this.$(".designer-panel").offset();
+ var canvasHeight=Ember.$(window).height()-panelOffset.top-25;
+ this.flowRenderer.initRenderer(function(){
this.renderWorkflow();
- }.bind(this));
+ }.bind(this),{context:this,flattenedNodes:this.get("flattenedNodes"),dataNodes:this.get("dataNodes"), cyOverflow:this.get("cyOverflow"),canvasHeight:canvasHeight});
},
renderWorkflow(){
- this.get('flattenedNodes').clear();
this.set('renderNodeTransitions', true);
- var visitedNodes=[];
- this.renderNodes(this.get("workflow").startNode,visitedNodes);
+ this.flowRenderer.renderWorkflow(this.get("workflow"));
+ this.doValidation();
},
rerender(){
- this.designerPlumb.detachEveryConnection();
+ this.flowRenderer.cleanup();
this.renderWorkflow(this.get("workflow"));
},
setCurrentTransition(transition){
this.set("currentTransition",transition);
},
- renderNodes(node,visitedNodes){
- if (!node || node.isKillNode()){
- return;
- }
- if (visitedNodes.contains(node)){
- return;
- }
- visitedNodes.push(node);
- if(!this.get('flattenedNodes').contains(node)){
- this.get('flattenedNodes').pushObject(node);
- }
- if (node.transitions.length > 0){
- node.transitions.forEach(function(transition) {
- var target = transition.targetNode;
- this.renderNodes(target,visitedNodes);
- }.bind(this));
- }
- },
- createConnection(sourceNode,target,transition){
- var connectionColor="#777";
- var lineWidth=1;
- if (transition.condition){
- if(transition.condition==="default"){
- lineWidth=2;
- }else if (transition.condition==="error"|| transition.errorPath){
- connectionColor=Constants.globalSetting.errorTransitionColor;
- }
- }
- var connectionObj={
- source:sourceNode.id,
- target:target.id,
- connector:["Straight"],
- paintStyle:{lineWidth:lineWidth,strokeStyle:connectionColor},
- endpointStyle:{fillStyle:'rgb(243,229,0)'},
- endpoint: ["Dot", {
- radius: 1
- }],
- alwaysRespectStubs:true,
- anchors: [["Bottom"],["Top"]],
- overlays:[]
- };
- return connectionObj;
+ actionInfo(node){
+ this.send("showNotification", node);
},
deleteTransition(transition){
+ this.createSnapshot();
this.get("workflow").deleteTransition(transition);
+ this.showUndo('transition');
this.rerender();
},
- renderTransitions(sourceNode,connections,visitedNodes){
+ showWorkflowActionSelect(element){
var self=this;
- if(!sourceNode){
- return;
- }
- if (visitedNodes.contains(sourceNode)){
- return;
- }
- if (sourceNode.hasTransition() ){
- var transitionCount=sourceNode.transitions.length;
- sourceNode.transitions.forEach(function(transition) {
- var target = transition.targetNode;
- if (target.isKillNode() || !Constants.showErrorTransitions && transition.isOnError()){
- return;
- }
- var connectionObj=self.createConnection(sourceNode,target,transition);
-
- if (transition.condition){
- var conditionHTML = "<div class='decision-condition' title='"+transition.condition+"'>"+ transition.condition+"</div>";
- connectionObj.overlays.push([ "Label", {label:conditionHTML, location:0.75, id:"myLabel" } ]);
- }
- if (!target.isPlaceholder()){
- connectionObj.overlays.push(["PlainArrow",{location:-0.1,width: 7,length: 7}]);
- }
- if (!(sourceNode.isPlaceholder() || target.isKillNode())){
- var location=target.type==="placeholder"?1:0.5;
- var addNodeoverlay=["Custom" , {
- id: sourceNode.id+"_"+target.id+"_"+"connector",
- location:location,
- create:function(component) {
- var container=Ember.$('<div />');
- var plus= Ember.$('<div class="fa fa-plus connector_overlay_new"></div>');
- if ((sourceNode.isDecisionNode() && transitionCount>1 ||sourceNode.isForkNode() && transitionCount>2 ) &&
- target.isPlaceholder() &&
- !transition.isDefaultCasePath()){
- var trash=Ember.$('<div class="node_actions node_left"><i class="fa fa-trash-o"></i></div>');
- trash.on("click",function(){
- self.deleteTransition(transition);
- });
- plus.append(trash);
- }
- container.append(plus);
- return container;
- },
- events:{
- click:function(labelOverlay, originalEvent) {
- var element = originalEvent.target;
- self.set('popOverElement', element);
- self.setCurrentTransition(transition);
- self.$('.popover').popover('destroy');
- Ember.$(element).parents(".jsplumb-overlay").css("z-index", "4");
- self.$(element).attr('data-toggle','popover');
- self.$(element).popover({
- html : true,
- title : "Add Node <button type='button' class='close'>×</button>",
- placement: 'right',
- trigger : 'focus',
- content : function(){
- return self.$('#workflow-actions').html();
- }
- });
- self.$(element).popover("show");
- self.$('.popover .close').on('click',function(){
- Ember.$(".jsplumb-overlay").css("z-index", "");
- self.$('.popover').popover('destroy');
- });
- }
- }
- }];
- connectionObj.overlays.push(addNodeoverlay);
- }
- connections.push(connectionObj);
- self.renderTransitions(target,connections,visitedNodes);
- });
- }
+ this.$('.popover').popover('destroy');
+ Ember.$(element).parents(".jsplumb-overlay").css("z-index", "4");
+ this.$(element).attr('data-toggle','popover');
+ this.$(element).popover({
+ html : true,
+ title : "Add Node <button type='button' class='close'>×</button>",
+ placement: 'right',
+ trigger : 'focus',
+ content : function(){
+ return self.$('#workflow-actions').html();
+ }
+ });
+ this.$(element).popover("show");
+ this.$('.popover .close').on('click',function(){
+ Ember.$(".jsplumb-overlay").css("z-index", "");
+ this.$('.popover').popover('destroy');
+ }.bind(this));
},
+
layout(){
- var nodes = Ember.$(".nodecontainer");
- //var edges = this.designerPlumb.getConnections();
- var edges=this.workflowConnections;
- this.layoutManager.doLayout(this,nodes,edges,this.get("workflow"));
- this.designerPlumb.repaintEverything();
- var endNodeTop=this.$("#node-end").offset().top;
- var endNodeLeft=this.$("#node-end").offset().left;
- this.$("#killnodes-container").offset({top:endNodeTop+50,left:endNodeLeft-50});
- var top = this.$("#killnodes-container").offset().top + 40;
- var left = this.$("#killnodes-container").offset().left - 28;
- this.$('.kill').each(function(index,value){
- this.$(value).offset({top:top,left:left});
- top = this.$(value).offset().top+70 ;
- }.bind(this));
+ this.flowRenderer.refresh();
},
doValidation(){
- this.set('validationErrors',[]);
- this.validate().then(() => {
- this.set('validationErrors',[]);
- }).catch(() => {
- this.get('flattenedNodes').filterBy('errors',true).forEach((node)=>{
- this.get('validationErrors').pushObjects(node.errorMsgs);
- }.bind(this));
-
- }.bind(this));
+ this.validate();
+ },
+ getStackTrace(data){
+ if(data){
+ try{
+ var stackTraceMsg = JSON.parse(data).stackTrace;
+ if(!stackTraceMsg){
+ return "";
+ }
+ if(stackTraceMsg instanceof Array){
+ return stackTraceMsg.join("").replace(/\tat /g, ' at ');
+ } else {
+ return stackTraceMsg.replace(/\tat /g, '<br/> at ');
+ }
+ } catch(err){
+ return "";
+ }
+ }
+ return "";
},
importWorkflow(filePath){
var self = this;
@@ -352,17 +296,34 @@ export default Ember.Component.extend(EmberValidations,{
workflowXmlDefered.promise.then(function(data){
this.importWorkflowFromString(data);
this.set("isWorkflowImporting", false);
- }.bind(this)).catch(function(e){
+ }.bind(this)).catch(function(data){
+ var stackTraceMsg = self.getStackTrace(data.responseText);
+ if(stackTraceMsg.length){
+ self.set("isStackTraceVisible", true);
+ self.set("stackTrace", stackTraceMsg);
+ self.set("isStackTraceAvailable", true);
+ } else {
+ self.set("isStackTraceVisible", false);
+ self.set("isStackTraceAvailable", false);
+ }
self.set("isWorkflowImporting", false);
self.set("isImportingSuccess", false);
});
},
importWorkflowFromString(data){
var workflow=this.get("workflowImporter").importWorkflow(data);
- this.resetDesigner();
- this.set("workflow",workflow);
- this.rerender();
- this.doValidation();
+ if(this.get('workflow')){
+ this.resetDesigner();
+ this.set("workflow",workflow);
+ this.initAndRenderWorkflow();
+ this.rerender();
+ this.doValidation();
+ }else{
+ this.workflow.initialize();
+ this.set("workflow",workflow);
+ this.initAndRenderWorkflow();
+ this.$('#wf_title').focus();
+ }
},
getWorkflowFromHdfs(filePath){
var url = Ember.ENV.API_URL + "/readWorkflowXml?workflowXmlPath="+filePath;
@@ -377,16 +338,16 @@ export default Ember.Component.extend(EmberValidations,{
}
}).done(function(data){
deferred.resolve(data);
- }).fail(function(){
- deferred.reject();
+ }).fail(function(data){
+ deferred.reject(data);
});
return deferred;
},
resetDesigner(){
this.set("isImportingSuccess", true);
- this.set("xmlAppPath", null)
- this.set('errors',{});
- this.set('validationErrors',{});
+ this.set("xmlAppPath", null);
+ this.set('errors',[]);
+ this.set('validationErrors',[]);
this.set('workflowFilePath',"");
this.get("workflow").resetWorfklow();
this.set('globalConfig', {});
@@ -395,7 +356,7 @@ export default Ember.Component.extend(EmberValidations,{
this.set('workflow.parameters', {});
}
this.set('parameters', {});
- this.designerPlumb.reset();
+ this.flowRenderer.reset();
},
resetZoomLevel(){
this.set("zoomLevel", 1);
@@ -423,33 +384,150 @@ export default Ember.Component.extend(EmberValidations,{
return deferred;
},
persistWorkInProgress(){
- //TODO later
+ var json=JSON.stringify(this.get("workflow"));
+ this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json);
+ },
+ getDraftWorkflow(){
+ var drafWorkflowJson = this.get('workspaceManager').restoreWorkInProgress(this.get('tabInfo.id'));
+ var workflowImporter=WorkflowJsonImporter.create({});
+ var workflow=workflowImporter.importWorkflow(drafWorkflowJson);
+ return workflow;
+ },
+ createSnapshot() {
+ this.set('undoAvailable', false);
+ this.set('workflowSnapshot', JSON.stringify(this.get("workflow")));
+ },
+ showUndo (type){
+ this.set('undoAvailable', true);
+ this.set('undoType', type);
+ },
+ deleteWorkflowNode(node){
+ this.createSnapshot();
+ if(node.isKillNode()){
+ var result=this.get("workflow").deleteKillNode(node);
+ if (result && result.status===false){
+ this.get('validationErrors').pushObject({node : node ,message :result.message});
+ }
+ } else {
+ this.get("workflow").deleteNode(node);
+ }
+ this.rerender();
+ this.doValidation();
+ this.showUndo('node');
+ },
+ addWorkflowBranch(node){
+ this.createSnapshot();
+ this.get("workflow").addBranch(node);
+ this.rerender();
+ },
+ openWorkflowEditor(node){
+ this.createSnapshot();
+ var validOkToNodes = WorkflowPathUtil.findValidTransitionsTo(this.get('workflow'), node);
+ this.set('showActionEditor', true);
+ this.set('currentAction', node.actionType);
+ var domain = node.getNodeDetail();
+ this.set('clonedDomain',Ember.copy(domain));
+ this.set('clonedErrorNode', node.errorNode);
+ this.set('clonedKillMessage',node.get('killMessage'));
+ node.set("domain", domain);
+ node.set("validOkToNodes", validOkToNodes);
+ this.set('currentNode', node);
+ },
+ openDecisionEditor(node) {
+ this.get("addBranchListener").trigger("showBranchOptions", node);
+ },
+
+ copyNode(node){
+ this.get('clipboardService').setContent(node, 'copy');
+ },
+ cutNode(node){
+ this.get('clipboardService').setContent(node, 'cut');
+ this.deleteWorkflowNode(node);
+ },
+ replaceNode(node){
+ var clipboardContent = this.get('clipboardService').getContent();
+ Ember.set(node, 'name', clipboardContent.name+'-copy');
+ Ember.set(node, 'domain', clipboardContent.domain);
+ Ember.set(node, 'actionType', clipboardContent.actionType);
+ this.rerender();
+ this.doValidation();
},
- restoreWorkinProgress(){
- //TODO later
+ scrollToNewPosition(){
+ if (Constants.useCytoscape){
+ return;
+ }
+ var scroll = Ember.$(window).scrollTop();
+ Ember.$('html, body')
+ .animate({
+ scrollTop: scroll+200
+ }, 1000);
+ },
+ openSaveWorkflow (){
+ this.get('workflowContext').clearErrors();
+ var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"),
+ workflowContext:this.get('workflowContext')});
+ var workflowXml=workflowGenerator.process();
+ if(this.get('workflowContext').hasErrors()){
+ this.set('errors',this.get('workflowContext').getErrors());
+ }else{
+ var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(workflowXml);
+ var configForSubmit={props:dynamicProperties,xml:workflowXml,params:this.get('workflow.parameters')};
+ this.set("workflowSubmitConfigs",configForSubmit);
+ this.set("showingSaveWorkflow",true);
+ }
+ },
+ openJobConfig (){
+ this.get('workflowContext').clearErrors();
+ var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"),
+ workflowContext:this.get('workflowContext')});
+ var workflowXml=workflowGenerator.process();
+ if(this.get('workflowContext').hasErrors()){
+ this.set('errors',this.get('workflowContext').getErrors());
+ }else{
+ var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(workflowXml);
+ var configForSubmit={props:dynamicProperties,xml:workflowXml,params:this.get('workflow.parameters')};
+ this.set("workflowSubmitConfigs",configForSubmit);
+ this.set("showingWorkflowConfigProps",true);
+ }
},
actions:{
+ showStackTrace(){
+ this.set("isStackTraceVisible", true);
+ },
+ hideStackTrace(){
+ this.set("isStackTraceVisible", false);
+ },
showWorkflowSla (value) {
this.set('showWorkflowSla', value);
},
showCreateKillNode (value){
- this.set('showCreateKillNode', value);
+ this.set('showKillNodeManager', value);
+ this.set('addKillNodeMode', true);
+ this.set('editMode', false);
+ },
+ showKillNodeManager (value){
+ this.set('showKillNodeManager', value);
+ this.set('addKillNodeMode', false);
+ },
+ closeKillNodeManager(){
+ this.set("showKillNodeManager", false);
},
showVersionSettings(value){
this.set('showVersionSettings', value);
},
- showParameterSettings(value){
+ showingParameterSettings(value){
if(this.get('workflow.parameters') !== null){
this.set('parameters', Ember.copy(this.get('workflow.parameters')));
}else{
- this.set('globalConfig', {});
+ this.set('parameters', {});
}
this.set('showParameterSettings', value);
},
showCredentials(value){
this.set('showCredentials', value);
},
- createKillNode(){
+ createKillNode(killNode){
+ this.set("killNode", killNode);
this.set("createKillnodeError",null);
var existingKillNode=this.get('workflow').get("killNodes").findBy("name",this.get('killNode.name'));
if (existingKillNode){
@@ -460,7 +538,7 @@ export default Ember.Component.extend(EmberValidations,{
this.set("createKillnodeError","The kill node cannot be empty");
return;
}
- this.get("workflow").createKillNode(this.get('killNode.name'),this.get('killNode.message'));
+ this.get("workflow").createKillNode(this.get('killNode.name'),this.get('killNode.killMessage'));
this.set('killNode',{});
this.rerender();
this.layout();
@@ -469,62 +547,89 @@ export default Ember.Component.extend(EmberValidations,{
this.set('showCreateKillNode', false);
},
addNode(type){
+ this.createSnapshot();
var currentTransition=this.get("currentTransition");
- var newNode=this.get("workflow").addNode(currentTransition,type);
- if(currentTransition.targetNode.isPlaceholder()){
- this.designerPlumb.remove(currentTransition.targetNode.id);
- }
+ this.get("workflow").addNode(this.findTransition(this.get("workflow").startNode, currentTransition.sourceNodeId, currentTransition.targetNode.id),type);
this.rerender();
this.doValidation();
- var scroll = $(window).scrollTop();
- Ember.$('html, body')
- .animate({
- scrollTop: scroll+200
- }, 1000);
+ this.scrollToNewPosition();
},
+
nameChanged(){
this.doValidation();
},
- deleteNode(node){
- if(node.isKillNode()){
- var result=this.get("workflow").deleteKillNode(node);
- if (result && result.status===false){
- this.get('validationErrors').pushObject({node : node ,message :result.message});
- }
- } else {
- this.get("workflow").deleteNode(node);
+ copyNode(node){
+ this.copyNode(node);
+ },
+ pasteNode(){
+ var clipboardContent = this.get('clipboardService').getContent();
+ var currentTransition = this.get("currentTransition");
+ var node = this.get("workflow").addNode(currentTransition, clipboardContent.actionType);
+ if(clipboardContent.operation === 'cut'){
+ node.name = clipboardContent.name;
+ }else{
+ node.name = clipboardContent.name + '-copy';
}
+ node.domain = clipboardContent.domain;
+ node.actionType = clipboardContent.actionType;
this.rerender();
this.doValidation();
+ this.scrollToNewPosition();
+ },
+ deleteNode(node){
+ this.deleteWorkflowNode(node);
},
openEditor(node){
- this.set('showActionEditor', true);
- this.set('currentAction', node.actionType);
- var domain = node.getNodeDetail();
- this.set('clonedDomain',Ember.copy(domain));
- this.set('clonedErrorNode', node.errorNode);
- this.set('clonedKillMessage',node.get('killMessage'));
- node.set("domain", domain);
- this.set('currentNode', node);
+ this.openWorkflowEditor(node);
+ },
+ setFilePath(filePath){
+ this.set("workflowFilePath", filePath);
+ },
+ showNotification(node){
+ this.set("showNotificationPanel", true);
+ if(node.actionType){
+ //this.set("hoveredWidget", node.actionType+"-action-info");
+ //this.set("hoveredAction", node.getNodeDetail());
+ }
+ },
+ hideNotification(){
+ this.set("showNotificationPanel", false);
},
addBranch(node){
- this.get("workflow").addBranch(node);
- this.rerender();
+ this.addWorkflowBranch(node);
},
addDecisionBranch(settings){
+ this.createSnapshot();
this.get("workflow").addDecisionBranch(settings);
this.rerender();
},
- addKillNode(errorNode){
+ setNodeTransitions(transition){
var currentNode= this.get("currentNode");
- if(errorNode && errorNode.isNew){
- this.get("workflow").addKillNode(currentNode,errorNode);
- this.get("workflow.killNodes").push(errorNode);
+ if(transition.errorNode && transition.errorNode.isNew){
+ this.get("workflow").addKillNode(currentNode,transition.errorNode);
+ this.get("workflow.killNodes").push(transition.errorNode);
}else {
- this.set('currentNode.errorNode', errorNode);
+ this.set('currentNode.errorNode', transition.errorNode);
}
+ currentNode.transitions.forEach((trans)=>{
+ if(transition.okToNode){
+ if(trans.targetNode.id !== transition.okToNode.id){
+ trans.targetNode = transition.okToNode;
+ this.showUndo('transition');
+ }
+ }
+ }, this);
},
submitWorkflow(){
+ this.set('dryrun', false);
+ this.openJobConfig();
+ },
+ saveWorkflow(){
+ this.set('dryrun', false);
+ this.openSaveWorkflow();
+ },
+ previewWorkflow(){
+ this.set("showingPreview",false);
this.get('workflowContext').clearErrors();
var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"),
workflowContext:this.get('workflowContext')});
@@ -532,15 +637,11 @@ export default Ember.Component.extend(EmberValidations,{
if(this.get('workflowContext').hasErrors()){
this.set('errors',this.get('workflowContext').getErrors());
}else{
- var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(workflowXml);
- var configForSubmit={props:dynamicProperties,xml:workflowXml,params:this.get('workflow.parameters')};
- this.set("workflowSubmitConfigs",configForSubmit);
- this.set("showingWorkflowConfigProps",true);
+ this.set("previewXml",vkbeautify.xml(workflowXml));
+ this.set("showingPreview",true);
}
-
},
- previewWorkflow(){
- this.set("showingPreview",false);
+ downloadWorkflowXml(){
this.get('workflowContext').clearErrors();
var workflowGenerator=WorkflowGenerator.create({workflow:this.get("workflow"),
workflowContext:this.get('workflowContext')});
@@ -548,12 +649,15 @@ export default Ember.Component.extend(EmberValidations,{
if(this.get('workflowContext').hasErrors()){
this.set('errors',this.get('workflowContext').getErrors());
}else{
- this.set("previewXml",vkbeautify.xml(workflowXml));
- this.set("showingPreview",true);
+ this.workflowXmlDownload(workflowXml);
}
},
closeWorkflowSubmitConfigs(){
this.set("showingWorkflowConfigProps",false);
+ this.set("showingSaveWorkflow",false);
+ },
+ closeSaveWorkflow(){
+ this.set("showingSaveWorkflow",false);
},
importWorkflowTest(){
var deferred = this.importSampleWorkflow();
@@ -563,6 +667,7 @@ export default Ember.Component.extend(EmberValidations,{
this.rerender();
this.doValidation();
}.bind(this)).catch(function(e){
+ console.error(e);
});
},
closeFileBrowser(){
@@ -625,7 +730,11 @@ export default Ember.Component.extend(EmberValidations,{
this.resetZoomLevel();
this.$("#flow-designer").css("transform", "scale(" + 1 + ")");
},
+ resetLayout() {
+ this.flowRenderer.resetLayout();
+ },
closeActionEditor (isSaved){
+ this.send("hideNotification");
if(isSaved){
this.currentNode.onSave();
this.doValidation();
@@ -638,6 +747,27 @@ export default Ember.Component.extend(EmberValidations,{
}
this.set('showActionEditor', false);
this.rerender();
+ },
+ saveDraft(){
+ this.persistWorkInProgress();
+ },
+
+ undoDelete () {
+ var workflowImporter = WorkflowJsonImporter.create({});
+ var workflow = workflowImporter.importWorkflow(this.get('workflowSnapshot'));
+ this.resetDesigner();
+ this.set("workflow", workflow);
+ this.rerender();
+ this.doValidation();
+ this.set('undoAvailable', false);
+ },
+
+ registerAddBranchAction(component){
+ this.set("addBranchListener",component);
+ },
+ dryRunWorkflow(){
+ this.set('dryrun', true);
+ this.openJobConfig();
}
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action-info.js
new file mode 100644
index 0000000..73cabac
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action-info.js
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action.js
index 98a292d..03acbf3 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/fs-action.js
@@ -15,11 +15,19 @@
* limitations under the License.
*/
import Ember from 'ember';
-import EmberValidations, {
- validator
-} from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'actionModel.fsOps': {
+ validators: [
+ validator('fs-action-validator', {
+ dependentKeys: ['actionModel.fsOps.@each']
+ })
+ ]
+ }
+});
+
+export default Ember.Component.extend(Validations, {
fileBrowser: Ember.inject.service('file-browser'),
setUp: function() {
if (this.get('actionModel.fsOps') === undefined) {
@@ -29,6 +37,8 @@ export default Ember.Component.extend(EmberValidations, {
this.set("actionModel.configuration", {});
this.set("actionModel.configuration.property", Ember.A([]));
}
+ var field = 'validations.attrs.actionModel.fsOps.isDirty';
+ this.set(field, false);
this.sendAction('register', 'fsAction', this);
}.on('init'),
initialize: function() {
@@ -41,52 +51,6 @@ export default Ember.Component.extend(EmberValidations, {
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations: {
- 'actionModel': {
- inline: validator(function() {
- var isValidated = true,
- msg = "";
- if (!this.get('actionModel.fsOps')) {
- return;
- }
- this.get('actionModel.fsOps').forEach(function(item, index) {
- switch (item.type) {
- case "mkdir":
- case "delete":
- case "touchz":
- if (!item.settings.path) {
- isValidated = false;
- msg = "path is mandatory";
- }
- break;
- case "chmod":
- if (!item.settings.path) {
- isValidated = false;
- msg = "path and permissions are mandatory";
- }
- break;
- case "chgrp":
- if (!item.settings.path || !item.settings.group) {
- isValidated = false;
- msg = "path and group are mandatory";
- }
- break;
- case "move":
- if (!item.settings.source || !item.settings.target) {
- isValidated = false;
- msg = "source and target are mandatory";
- }
- break;
- }
- });
- if (!isValidated) {
- return " ";
- }
-
- })
- }
- },
-
actions: {
openFileBrowser(model, context) {
if (undefined === context) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/fsaction-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/fsaction-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/fsaction-info.js
new file mode 100644
index 0000000..caf23b4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/fsaction-info.js
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
index fc5fd37..c9be41a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hdfs-browser.js
@@ -57,7 +57,7 @@ export default Ember.Component.extend({
},
createFolder(){
var self=this;
- var $elem=this.$("#selectedPath");
+ var $elem=this.$('input[name="selectedPath"]');
//$elem.val($elem.val()+"/");
var folderHint="<enter folder here>";
this.set("selectedPath",this.get("selectedPath")+"/"+folderHint);
@@ -98,7 +98,8 @@ export default Ember.Component.extend({
this.showNotification({
"type": "error",
"message": "Upload Failed",
- "details":textStatus
+ "details":textStatus,
+ "errorThrown":errorThrown
});
},
uploadProgress(e){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action-info.js
new file mode 100644
index 0000000..73cabac
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action-info.js
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action.js
index 125aac3..ac85a9a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive-action.js
@@ -16,9 +16,25 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel.script': validator('presence', {
+ presence : true,
+ disabled(model, attribute) {
+ return !model.get('isScript');
+ },
+ dependentKeys : ['isScript']
+ }),
+ 'actionModel.query': validator('presence', {
+ presence : true,
+ disabled(model, attribute) {
+ return model.get('isScript');
+ },
+ dependentKeys : ['isScript']
+ })
+});
+export default Ember.Component.extend(Validations, {
hiveOptionObserver : Ember.observer('isScript',function(){
if(this.get('isScript')){
this.set("actionModel.query", undefined);
@@ -68,20 +84,6 @@ export default Ember.Component.extend(EmberValidations,{
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.script': {
- presence: {
- 'if':'isScript',
- 'message' : 'You need to provide a value for Script'
- }
- },
- 'actionModel.query': {
- presence: {
- unless :'isScript',
- 'message' : 'You need to provide a value for Query'
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
@@ -95,9 +97,9 @@ export default Ember.Component.extend(EmberValidations,{
},
onHiveOptionChange(value){
if(value === "script"){
- this.set('isScript',true);
+ this.set('isScript', true);
}else{
- this.set('isScript',false);
+ this.set('isScript', false);
}
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action.js
index f8b53c5..f23cca7 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/hive2-action.js
@@ -16,9 +16,30 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel.script': validator('presence', {
+ presence : true,
+ disabled(model, attribute) {
+ return !model.get('isScript');
+ },
+ dependentKeys : ['isScript']
+ }),
+ 'actionModel.query': validator('presence', {
+ presence : true,
+ disabled(model, attribute) {
+ return model.get('isScript');
+ },
+ dependentKeys : ['isScript']
+ }),
+ 'actionModel.jdbc-url': validator('presence', {
+ presence : true
+ })
+
+});
+
+export default Ember.Component.extend(Validations,{
hiveOptionObserver : Ember.observer('isScript',function(){
if(this.get('isScript')){
this.set("actionModel.query", undefined);
@@ -68,25 +89,6 @@ export default Ember.Component.extend(EmberValidations,{
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.script': {
- presence: {
- 'if':'isScript',
- 'message' : 'You need to provide a value for Script'
- }
- },
- 'actionModel.query': {
- presence: {
- unless :'isScript',
- 'message' : 'You need to provide a value for Query'
- }
- },
- 'actionModel.jdbc-url': {
- presence: {
- 'message' : 'You need to provide a value for jdbc url'
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/info-header.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/info-header.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/info-header.js
new file mode 100644
index 0000000..73cabac
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/info-header.js
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/instance-list-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/instance-list-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/instance-list-config.js
new file mode 100644
index 0000000..c46a37f
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/instance-list-config.js
@@ -0,0 +1,54 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ multivalued : true,
+ instance : {
+ value : '',
+ displayValue : '',
+ type : 'date'
+ },
+ initialize : function(){
+ this.sendAction('register', this, this);
+ this.on('bindInputPlaceholder',function () {
+ this.set('addUnboundValue', true);
+ }.bind(this));
+ }.on('init'),
+ bindInputPlaceholder : function () {
+ if(this.get('addUnboundValue') && !Ember.isBlank(this.get('instance'))){
+ this.addinstance();
+ }
+ }.on('willDestroyElement'),
+ addInstance (){
+ this.get('instances').pushObject(Ember.copy(this.get('instance')));
+ this.set('instance', {
+ value : '',
+ displayValue : '',
+ type : 'date'
+ });
+ },
+ actions : {
+ addInstance () {
+ this.addInstance();
+ },
+ deleteInstance (index) {
+ this.get('instances').removeAt(index);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action.js
index 873c284..9d43fe7 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/java-action.js
@@ -16,9 +16,18 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'actionModel.mainClass': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.jobTracker': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations, {
fileBrowser : Ember.inject.service('file-browser'),
javaOptsObserver : Ember.observer('isSingle',function(){
if(this.get('isSingle')){
@@ -67,18 +76,6 @@ export default Ember.Component.extend(EmberValidations, {
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.mainClass': {
- presence: {
- 'message' : 'You need to provide a value for Main Class',
- },
- format: {
- with: /([a-z][a-z_0-9]*\.)*[A-Za-z_]($[A-Za-z_]|[\w_])*/,
- allowBlank: false,
- message: 'You need to provide a valid value'
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
new file mode 100644
index 0000000..4fa2666
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-config.js
@@ -0,0 +1,303 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+import Constants from '../utils/constants';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'filePath': validator('presence', {
+ presence : true
+ }),
+ 'configMap': {
+ validators: [
+ validator('job-params-validator', {
+ dependentKeys: ['configMap.@each.value', 'showErrorMessage']
+ })
+ ]
+ }
+});
+
+
+export default Ember.Component.extend(Validations, {
+ systemConfigs : Ember.A([]),
+ showingFileBrowser : false,
+ jobXml : "",
+ overwritePath : false,
+ configMap : Ember.A([]),
+ configPropsExists : false,
+ savingInProgress : false,
+ isStackTraceVisible: false,
+ isStackTraceAvailable: false,
+ alertType : "",
+ alertMessage : "",
+ alertDetails : "",
+ filePath : "",
+ showErrorMessage: false,
+ displayName : Ember.computed('type', function(){
+ if(this.get('type') === 'wf'){
+ return "Workflow";
+ }else if(this.get('type') === 'coord'){
+ return "Coordinator";
+ }else{
+ return "Bundle";
+ }
+ }),
+ initialize :function(){
+ this.set("configPropsExists", this.get("jobConfigs").props.size>0);
+ var configProperties = [];
+ configProperties.pushObjects(this.extractJobParams());
+ configProperties.pushObjects(this.extractJobProperties());
+ this.configureExecutionSettings();
+ this.set("configMap", configProperties);
+ this.set("jobXml", this.get("jobConfigs").xml);
+ this.set('filePath', Ember.copy(this.get('jobFilePath')));
+ Object.keys(this.get('validations.attrs')).forEach((attr)=>{
+ var field = 'validations.attrs.'+attr+'.isDirty';
+ this.set(field, false);
+ }, this);
+ }.on('init'),
+ rendered : function(){
+ this.$("#configureJob").on('hidden.bs.modal', function () {
+ this.sendAction('closeJobConfigs');
+ }.bind(this));
+ this.$("#configureJob").modal("show");
+ }.on('didInsertElement'),
+ extractJobParams(){
+ var params = [];
+ var jobParams = this.get("jobConfigs").params;
+ if(jobParams && jobParams.configuration && jobParams.configuration.property){
+ jobParams.configuration.property.forEach((param)=>{
+ if(param && !param.value){
+ var prop= Ember.Object.create({
+ name: param.name,
+ value: null,
+ isRequired : true
+ });
+ params.push(prop);
+ }
+ });
+ }
+ return params;
+ },
+
+ extractJobProperties(){
+ var jobProperties = [];
+ var jobParams = this.get("jobConfigs").params;
+ this.get("jobConfigs").props.forEach(function(value) {
+ if (value!== Constants.defaultNameNodeValue && value!==Constants.rmDefaultValue){
+ var propName = value.trim().substring(2, value.length-1);
+ var isRequired = true;
+ if(jobParams && jobParams.configuration && jobParams.configuration.property){
+ var param = jobParams.configuration.property.findBy('name', propName);
+ if(param && param.value){
+ isRequired = false;
+ }else {
+ isRequired = true;
+ }
+ }
+ var prop= Ember.Object.create({
+ name: propName,
+ value: null,
+ isRequired : isRequired
+ });
+ jobProperties.push(prop);
+ }
+ });
+ return jobProperties;
+ },
+ configureExecutionSettings (){
+ this.set('systemConfigs', Ember.A([]));
+ if(this.get('type') !== 'coord' && !this.get('isDryrun')){
+ this.get('systemConfigs').pushObject({displayName: 'Run on submit', name : 'runOnSubmit', value: false});
+ }
+ this.get('systemConfigs').pushObjects([
+ {displayName: 'Use system lib path', name :'useSystemLibPath', value:true},
+ {displayName: 'Rerun on Failure', name : 'rerunOnFailure', value:true}
+ ]);
+ },
+ showNotification(data){
+ if (!data){
+ return;
+ }
+ if (data.type === "success"){
+ this.set("alertType", "success");
+ }
+ if (data.type === "error"){
+ this.set("alertType", "danger");
+ }
+ this.set("alertDetails", data.details);
+ this.set("alertMessage", data.message);
+ if(data.stackTrace.length){
+ this.set("stackTrace", data.stackTrace);
+ this.set("isStackTraceAvailable", true);
+ } else {
+ this.set("isStackTraceAvailable", false);
+ }
+ },
+ prepareJobForSubmission(isDryrun){
+ if(this.get('validations.isInvalid')){
+ return;
+ };
+ this.set('jobFilePath', Ember.copy(this.get('filePath')));
+ var url = Ember.ENV.API_URL + "/submitJob?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath");
+ url = url + "&jobType=" + this.get('displayName').toUpperCase();
+ var submitConfigs = this.get("configMap");
+ submitConfigs.forEach(function(item) {
+ url = url + "&config." + item.name + "=" + item.value;
+ }, this);
+ this.get('systemConfigs').forEach((config)=>{
+ if(config.name === 'runOnSubmit' && !isDryrun){
+ url = url + "&oozieparam.action=start";
+ }else if(config.name !== 'runOnSubmit'){
+ url = url + "&oozieconfig." + config.name + "=" + config.value;
+ }
+ });
+ if(isDryrun){
+ url = url + "&oozieparam.action=dryrun";
+ }
+ if ( this.get("jobConfigs").props.has("${resourceManager}")){
+ url= url + "&resourceManager=useDefault";
+ }
+ this.set("savingInProgress", true);
+ this.submitJob(url);
+ },
+ submitJob(url){
+ Ember.$.ajax({
+ url: url,
+ method: "POST",
+ dataType: "text",
+ contentType: "text/plain;charset=utf-8",
+ beforeSend: function(request) {
+ request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ request.setRequestHeader("X-Requested-By", "workflow-designer");
+ },
+ data: this.get("jobXml"),
+ success: function(response) {
+ var result=JSON.parse(response);
+ this.showNotification({
+ "type": "success",
+ "message": this.get('displayName') +" saved.",
+ "details": "Job id :"+result.id
+ });
+ this.set("savingInProgress",false);
+ }.bind(this),
+ error: function(response) {
+ console.log(response);
+ this.set("savingInProgress",false);
+ this.set("isStackTraceVisible",true);
+ this.showNotification({
+ "type": "error",
+ "message": "Error occurred while saving "+ this.get('displayName').toLowerCase(),
+ "details": this.getParsedErrorResponse(response),
+ "stackTrace": this.getStackTrace(response.responseText)
+ });
+ }.bind(this)
+ });
+ },
+ getStackTrace(data){
+ if(data){
+ try{
+ var stackTraceMsg = JSON.parse(data).stackTrace;
+ if(!stackTraceMsg){
+ return "";
+ }
+ if(stackTraceMsg instanceof Array){
+ return stackTraceMsg.join("").replace(/\tat /g, '<br/> at ');
+ } else {
+ return stackTraceMsg.replace(/\tat /g, '<br/> at ');
+ }
+ } catch(err){
+ return "";
+ }
+ }
+ return "";
+ },
+ startJob (jobId){
+ this.set('startingInProgress', true);
+ var url = [Ember.ENV.API_URL,
+ "/v2/job/", jobId, "?action=", 'start','&user.name=oozie'
+ ].join("");
+ Ember.$.ajax({
+ url: url,
+ method: 'PUT',
+ beforeSend: function (xhr) {
+ xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ xhr.setRequestHeader("X-Requested-By", "Ambari");
+ }
+ }).done(function(){
+ this.set('startingInProgress', false);
+ this.showNotification({
+ "type": "success",
+ "message": this.get('displayName')+" Started",
+ "details": jobId
+ });
+ }.bind(this)).fail(function(response){
+ this.set('startingInProgress', false);
+ this.showNotification({
+ "type": "error",
+ "message": "Error occurred while starting "+ this.get('displayName').toLowerCase(),
+ "details": this.getParsedErrorResponse(response),
+ "stackTrace": this.getStackTrace(response.responseText)
+ });
+ }.bind(this));
+ },
+ getParsedErrorResponse (response){
+ var detail;
+ if (response.responseText && response.responseText.charAt(0)==="{"){
+ var jsonResp=JSON.parse(response.responseText);
+ if (jsonResp.status==="workflow.oozie.error"){
+ detail="Oozie error. Please check the workflow.";
+ }else if(jsonResp.message && jsonResp.message.indexOf("<html>") > -1){
+ detail= "";
+ }else{
+ detail=jsonResp.message;
+ }
+ }else{
+ detail=response;
+ }
+ return detail;
+ },
+ actions: {
+ selectFile(){
+ this.set("showingFileBrowser",true);
+ },
+ showStackTrace(){
+ this.set("isStackTraceVisible", true);
+ },
+ hideStackTrace(){
+ this.set("isStackTraceVisible", false);
+ },
+ closeFileBrowser(){
+ this.set("showingFileBrowser",false);
+ },
+ dryrun(){
+ this.set('showErrorMessage', true);
+ this.prepareJobForSubmission(true);
+ },
+ save(){
+ this.set('showErrorMessage', true);
+ this.prepareJobForSubmission(false);
+ },
+ previewXml(){
+ this.set("showingPreview",true);
+ },
+ closePreview(){
+ this.set("showingPreview",false);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
index ce78e59..e403dc4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/job-details.js
@@ -16,8 +16,12 @@
*/
import Ember from 'ember';
+import {WorkflowImporter} from '../domain/workflow-importer';
+import {ActionTypeResolver} from "../domain/action-type-resolver";
export default Ember.Component.extend({
+ workflowImporter: WorkflowImporter.create({}),
+ actionTypeResolver: ActionTypeResolver.create({}),
error : {},
errorMessage : Ember.computed('error', function() {
if(this.get('error').status === 400){
@@ -57,85 +61,342 @@ export default Ember.Component.extend({
}),
initialize : function(){
if(this.get('currentTab')){
- this.$('.nav-tabs a[href="'+this.get('currentTab').attr("href")+'"]').tab('show');
+ this.$('.nav-tabs a[href="'+this.get('currentTab').attr("href")+'"]').click();
if(this.get('model.actions')){
this.set('model.actionDetails', this.get('model.actions')[0]);
}
}
+
+ var x2js = new X2JS();
+ var configurationObj = x2js.xml_str2json(this.get('model.conf'));
+ this.set('model.configurationProperties', configurationObj.configuration.property);
+
this.$('.nav-tabs').on('shown.bs.tab', function(event){
this.sendAction('onTabChange', this.$(event.target));
}.bind(this));
}.on('didInsertElement'),
- actions : {
- back (){
- this.sendAction('back');
- },
- close : function(){
- this.sendAction('close');
- },
- doRefresh : function(){
- this.sendAction('doRefresh');
- },
- getJobDefinition : function () {
- Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=definition&timezone=GMT',function(response){
- this.set('model.jobDefinition', (new XMLSerializer()).serializeToString(response).trim());
- }.bind(this)).fail(function(error){
- this.set('error',error);
- }.bind(this));
- },
- showFirstActionDetail : function(){
- this.set('model.actionDetails', this.get('model.actions')[0]);
- },
- getJobLog : function (params){
- var url = Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=log';
- if(params && params.logFilter){
- url = url + '&logfilter=' + params.logFilter;
+
+ getShape(nodeType) {
+ switch(nodeType) {
+ case 'start' :
+ case 'end' :
+ case 'kill' :
+ case 'fork' :
+ case 'join' :
+ return 'ellipse';
+ case 'action' :
+ return 'roundrectangle';
+ case 'decision' :
+ return 'diamond';
+ default :
+ return 'star';
+ }
+ },
+
+ getNodeActionByName(workflowActions, nodeName) {
+ if (Ember.isArray(workflowActions)) {
+ var actionInfo = workflowActions.filter(function (modelAction) {
+ return modelAction.name === nodeName;
+ });
+ return actionInfo.length>0 ? actionInfo[0] : null;
+ } else {
+ return workflowActions;
+ }
+ },
+
+ getActionStatus(nodeName, nodeType) {
+ if (nodeType === 'start') {
+ nodeName = ':start:';
+ }
+ var nodeAction = this.getNodeActionByName(this.get('model.actions'), nodeName);
+
+ if (nodeAction) {
+ return nodeAction.status;
+ }
+ return "Not-Visited";
+ },
+
+ getNodeActionType(workflowXmlString, nodeType, nodeName) {
+ if (nodeType !== 'action') {
+ return nodeType;
+ }
+
+ var workflowJson = new X2JS().xml_str2json(workflowXmlString);
+
+ if (Ember.isArray(workflowJson['workflow-app'].action)) {
+ var workflowActionJson = workflowJson['workflow-app'].action.filter(function (workflowAction) {
+ return workflowAction._name === nodeName;
+ });
+ if (workflowActionJson.length>0) {
+ return this.actionTypeResolver.getActionType(workflowActionJson[0]);
}
- if(params && params.logActionList){
- url = url + '&type=action&scope='+ params.logActionList;
+ } else {
+ return this.actionTypeResolver.getActionType(workflowJson['workflow-app'].action);
+ }
+ return '';
+ },
+
+ getBgColorBasedOnStatus(nodeStatus) {
+ switch(nodeStatus) {
+ case 'Not-Visited' :
+ return '#ffffff';
+ default :
+ return '#e6e6e6';
+ }
+ },
+
+ getFontColorBasedOnStatus(nodeStatus) {
+ switch(nodeStatus) {
+ case 'ERROR' :
+ case 'KILLED' :
+ case 'FAILED' :
+ return '#a94442';
+ default :
+ return '#262626';
+ }
+ },
+
+ getBorderColorBasedOnStatus(nodeStatus) {
+ switch(nodeStatus) {
+ case 'OK' :
+ return '#5bb75b';
+ case 'ERROR' :
+ case 'KILLED' :
+ case 'FAILED' :
+ return '#a94442';
+ default :
+ return '#808080';
+ }
+ },
+
+ getNodeLabelContent(nodeType) {
+ switch(nodeType) {
+ case 'fork' :
+ return '\uf0e8';
+ case 'join' :
+ return '\uf0e8';
+ default :
+ return '';
+ }
+ },
+
+ getCyDataNodes(workflow){
+ var dataNodes = [];
+ var self=this;
+ workflow.nodeVisitor.process(workflow.startNode, function(node) {
+ if (node.type === 'kill') {
+ return;
}
- Ember.$.get(url,function(response){
- this.set('model.jobLog', response);
- }.bind(this)).fail(function(error){
- this.set('error', error);
- }.bind(this));
+ var nodeActionStatus = self.getActionStatus(node.name, node.type);
+ dataNodes.push({ data:
+ { id: node.id, name: node.name, type: node.type,
+ content: node.name + self.getNodeLabelContent(node.type),
+ shape: self.getShape(node.type),
+ bgColor: self.getBgColorBasedOnStatus(nodeActionStatus),
+ fontColor: self.getFontColorBasedOnStatus(nodeActionStatus),
+ borderColor: self.getBorderColorBasedOnStatus(nodeActionStatus) }
+ });
+ if (node.transitions.length > 0) {
+ node.transitions.forEach(function(tran){
+ if (tran.targetNode.type === 'kill') {
+ return;
+ }
+ dataNodes.push(
+ {
+ data: {
+ id: tran.sourceNodeId + '_to_' + tran.targetNode.id,
+ source:tran.sourceNodeId,
+ target: tran.targetNode.id,
+ borderColor: (self.getActionStatus(tran.targetNode.name, tran.targetNode.type) === 'Not-Visited')
+ ? '#808080' : self.getBorderColorBasedOnStatus(nodeActionStatus)
+ }
+ }
+ );
+ });
+ }
+ });
+ return dataNodes;
},
- getErrorLog : function (){
- Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=errorlog',function(response){
- this.set('model.errorLog', response);
- }.bind(this)).fail(function(error){
- this.set('error', error);
- }.bind(this));
+ showActionNodeDetail(node, workflowXmlString){
+ var nodeName = node.data().name;
+ if (nodeName === 'Start') {
+ nodeName = ':start:';
+ }
+ this.set('model.nodeName', nodeName);
+ this.set('model.nodeType', this.getNodeActionType(workflowXmlString, node.data().type, nodeName));
+ this.set('model.actionDetails', null);
+ var actionInfo = this.getNodeActionByName(this.get('model.actions'), nodeName);
+ this.set('model.actionInfo', actionInfo);
},
- getAuditLog : function (){
- Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=auditlog',function(response){
- this.set('model.auditLog', response);
- }.bind(this)).fail(function(error){
- this.set('error', error);
+ renderDag(xmlString){
+ var workflow = this.get("workflowImporter").importWorkflow(xmlString);
+ console.log("Workflow Object..", workflow);
+ var dataNodes=this.getCyDataNodes(workflow);
+ var cy = cytoscape({
+ container: document.getElementById('cy'),
+ elements: dataNodes,
+ style: [
+ {
+ selector: 'node',
+ style: {
+ shape: 'data(shape)',
+ 'color': 'data(fontColor)',
+ 'background-color': 'data(bgColor)',
+ 'border-width': 1,
+ 'border-color': 'data(borderColor)',
+ label: 'data(name)',
+ 'text-valign': 'center',
+ 'font-size': 8
+ }
+ },
+ {
+ selector: 'node[shape = "roundrectangle"]',
+ style: {
+ width: 100,
+ 'border-radius': 1,
+ }
+ },
+ {
+ selector: 'node[type = "fork"]',
+ style: {
+ 'background-image': 'assets/sitemap.png',
+ 'text-halign': 'left'
+ }
+ },
+ {
+ selector: 'node[type = "join"]',
+ style: {
+ 'background-image': 'assets/join.png',
+ 'text-halign': 'left'
+ }
+ },
+ {
+ selector: 'edge',
+ style: {
+ width: 1,
+ 'line-color': 'data(borderColor)',
+ 'curve-style': 'bezier',
+ 'target-arrow-shape': 'triangle',
+ 'target-arrow-color': 'data(borderColor)'
+ }
+ }
+ ],
+ layout: {
+ name: 'dagre'
+ }
+ });
+
+ // the default values of each option are outlined below:
+ var defaults = {
+ zoomFactor: 2.0, // zoom factor per zoom tick
+ minZoom: 0.1, // min zoom level
+ maxZoom: 10, // max zoom level
+
+ // icon class names
+ sliderHandleIcon: 'fa fa-minus',
+ zoomInIcon: 'fa fa-plus',
+ zoomOutIcon: 'fa fa-minus',
+ resetIcon: 'fa fa-expand'
+ };
+
+ cy.panzoom( defaults );
+
+ cy.on('click', 'node', function(event) {
+ var node = event.cyTarget;
+ this.showActionNodeDetail(node, xmlString);
}.bind(this));
},
- getJobDag : function (){
- this.set('model.jobDag', Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=graph');
+ importSampleWorkflow (){
+ var self=this;
+ Ember.$.ajax({
+ url: "/sampledata/workflow.xml",
+ dataType: "text",
+ cache:false,
+ success: function(data) {
+ self.renderDag(data);
+ }.bind(this),
+ failure : function(data){
+ console.error(data);
+ }
+ });
},
- getCoordActionReruns : function () {
- var url = Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=allruns&type=action';
- if(this.get('rerunActionList')){
- url = url + '&scope=' + this.get('rerunActionList');
+ actions : {
+ back (){
+ this.sendAction('back');
+ },
+ close : function(){
+ this.sendAction('close');
+ },
+ doRefresh : function(){
+ this.sendAction('doRefresh');
+ },
+ getJobDefinition : function () {
+ Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=definition&timezone=GMT',function(response){
+ this.set('model.jobDefinition', (new XMLSerializer()).serializeToString(response).trim());
+ }.bind(this)).fail(function(error){
+ this.set('error',error);
+ }.bind(this));
+ },
+ showFirstActionDetail : function(){
+ this.set('model.actionDetails', this.get('model.actions')[0]);
+ },
+ getJobLog : function (params){
+ var url = Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=log';
+ if(params && params.logFilter){
+ url = url + '&logfilter=' + params.logFilter;
+ }
+ if(params && params.logActionList){
+ url = url + '&type=action&scope='+ params.logActionList;
+ }
+ Ember.$.get(url,function(response){
+ this.set('model.jobLog', response);
+ }.bind(this)).fail(function(error){
+ this.set('error', error);
+ }.bind(this));
+ },
+ getErrorLog : function (){
+ Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=errorlog',function(response){
+ this.set('model.errorLog', response);
+ }.bind(this)).fail(function(error){
+ this.set('error', error);
+ }.bind(this));
+ },
+ getAuditLog : function (){
+ Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=auditlog',function(response){
+ this.set('model.auditLog', response);
+ }.bind(this)).fail(function(error){
+ this.set('error', error);
+ }.bind(this));
+ },
+ getJobDag : function (){
+ //if (true) return this.importSampleWorkflow();
+ Ember.$.get(Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=definition&timezone=GMT',function(response){
+ var xmlString = (new XMLSerializer()).serializeToString(response).trim();
+ this.renderDag(xmlString);
+ }.bind(this)).fail(function(error){
+ this.set('error',error);
+ }.bind(this));
+ // this.set('model.jobDag', Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=graph');
+ },
+ getCoordActionReruns : function () {
+ var url = Ember.ENV.API_URL+'/v2/job/'+this.get('id')+'?show=allruns&type=action';
+ if(this.get('rerunActionList')){
+ url = url + '&scope=' + this.get('rerunActionList');
+ }
+ Ember.$.get(url, function(response){
+ this.set('model.coordActionReruns', response.workflows);
+ }.bind(this)).fail(function(error){
+ this.set('error', error);
+ }.bind(this));
+ },
+ getActionDetails : function (actionInfo) {
+ this.set('model.actionDetails', actionInfo);
+ },
+ showWorkflow : function(workflowId){
+ this.sendAction('showWorkflow', workflowId);
+ },
+ showCoord : function(coordId){
+ this.sendAction('showCoord', coordId);
}
- Ember.$.get(url, function(response){
- this.set('model.coordActionReruns', response.workflows);
- }.bind(this)).fail(function(error){
- this.set('error', error);
- }.bind(this));
- },
- getActionDetails : function (actionInfo) {
- this.set('model.actionDetails', actionInfo);
- },
- showWorkflow : function(workflowId){
- this.sendAction('showWorkflow', workflowId);
- },
- showCoord : function(coordId){
- this.sendAction('showCoord', coordId);
}
- }
-});
+ });
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-config.js
new file mode 100644
index 0000000..cc9eb1e
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-config.js
@@ -0,0 +1,29 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ actions: {
+ createKillNode() {
+ this.sendAction('createKillNode');
+ },
+
+ updateNode() {
+ this.sendAction('updateNode');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-manager.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-manager.js
new file mode 100644
index 0000000..02660be
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/killnode-manager.js
@@ -0,0 +1,62 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ initialize : function() {
+ this.set('killNode', {});
+ this.set('editMode', false);
+ }.on('init'),
+
+ rendered : function(){
+ this.$('#killnode-manager-dialog').modal({
+ backdrop: 'static',
+ keyboard: false
+ });
+ this.$('#killnode-manager-dialog').modal('show');
+ this.$('#killnode-manager-dialog').modal().on('hidden.bs.modal', function() {
+ this.sendAction('closeKillNodeManager');
+ }.bind(this));
+ }.on('didInsertElement'),
+ actions: {
+ deleteNode(index) {
+ this.get('killNodes').removeAt(index);
+ this.set('editMode', false);
+ },
+ addNode() {
+ this.set('createKillnodeError',null);
+ this.set('editMode', false);
+ this.set('addKillNodeMode', true);
+ this.set('killNode', {});
+ },
+ editNode(index) {
+ this.set('createKillnodeError', null);
+ this.set('editMode', true);
+ this.set('currentKillNodeIndex', index);
+ var selectedKillNode = this.get('killNodes').objectAt(index);
+ this.set('killNode', {name : selectedKillNode.name, killMessage: selectedKillNode.killMessage});
+ },
+ updateNode(){
+ this.set('editMode', false);
+ this.get('killNodes').objectAt(this.get('currentKillNodeIndex')).set('killMessage', this.get('killNode').killMessage);
+ this.set('killNode', {});
+ },
+ createKillNode() {
+ this.sendAction('createKillNode', this.get("killNode"));
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/map-red-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/map-red-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/map-red-action.js
index c3782a3..3eb8545 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/map-red-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/map-red-action.js
@@ -16,9 +16,8 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations, {
+export default Ember.Component.extend({
hasStaticProps : true,
fileBrowser : Ember.inject.service('file-browser'),
staticProps : Ember.A([]),
@@ -65,9 +64,6 @@ export default Ember.Component.extend(EmberValidations, {
}.bind(this));
this.sendAction('register','mapRedAction', this);
}.on('didInsertElement'),
- validations : {
-
- },
observeError :function(){
if(this.$('#collapseOne label.text-danger').length > 0 && !this.$('#collapseOne').hasClass("in")){
this.$('#collapseOne').collapse('show');
[09/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/conditional-data-input.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/conditional-data-input.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/conditional-data-input.js
new file mode 100644
index 0000000..83d8a8e
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/conditional-data-input.js
@@ -0,0 +1,78 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'condition.operator': validator('presence', {
+ presence : true
+ }),
+ 'condition.operands': {
+ validators: [
+ validator('operand-length', {
+ min : 2,
+ dependentKeys: ['condition.operands.[]','condition.operator']
+ })
+ ]
+ }
+});
+
+export default Ember.Component.extend(Validations, {
+ initialize : function(){
+ this.set('conditionsList', Ember.A([]));
+ this.get('conditionsList').pushObjects([
+ {value : 'and', displayName: 'All'},
+ {value : 'or', displayName: 'Any'}
+ ]);
+ if(!this.get('isToplevel')){
+ this.get('conditionsList').pushObject({value : 'combine', displayName: 'Combine'});
+ }
+ this.sendAction('register', this, this);
+ }.on('init'),
+ onDestroy : function(){
+ this.sendAction('deregister', this);
+ }.on('willDestroyElement'),
+ actions : {
+ registerChild (key, context){
+ this.sendAction('register', key, context);
+ },
+ deregisterChild(key){
+ this.sendAction('deregister', key);
+ },
+ addCondition(){
+ if(!this.get('condition.operands')){
+ this.set('condition.operands', Ember.A([]));
+ }
+ this.get('condition.operands').pushObject({operands : Ember.A([]), type:'condition'});
+ },
+ addDataInput(){
+ if(!this.get('condition.operands')){
+ this.set('condition.operands', Ember.A([]));
+ }
+ this.get('condition.operands').pushObject({type:'dataInput'});
+ },
+ deleteOperand(index){
+ this.get('condition.operands').removeAt(index);
+ },
+ showAdvanced(){
+ this.set('showAdvanced', true);
+ },
+ hideAdvanced(){
+ this.set('showAdvanced', false);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/confirmation-dialog.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/confirmation-dialog.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/confirmation-dialog.js
new file mode 100644
index 0000000..6f726f0
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/confirmation-dialog.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ actions : {
+ onOk (){
+ this.sendAction('onOk');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
new file mode 100644
index 0000000..57fcdf8
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-config.js
@@ -0,0 +1,521 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import {Coordinator} from '../domain/coordinator/coordinator';
+import {CoordinatorGenerator} from '../domain/coordinator/coordinator-xml-generator';
+import {CoordinatorXmlImporter} from '../domain/coordinator/coordinator-xml-importer';
+import {SlaInfo} from '../domain/sla-info';
+import Constants from '../utils/constants';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'coordinator.name': validator('presence', {
+ presence : true
+ }),
+ 'coordinator.workflow.appPath': validator('presence', {
+ presence : true
+ }),
+ 'coordinator.frequency.value': validator('presence', {
+ presence : true
+ }),
+ 'coordinator.frequency.type': validator('presence', {
+ presence : true
+ }),
+ 'coordinator.timezone': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations, Ember.Evented, {
+ coordinator : null,
+ childComponents : new Map(),
+ fileBrowser : Ember.inject.service('file-browser'),
+ propertyExtractor : Ember.inject.service('property-extractor'),
+ workspaceManager : Ember.inject.service('workspace-manager'),
+ showErrorMessage: Ember.computed.alias('saveAttempted'),
+ datasetsForInputs : Ember.computed('coordinator.datasets.[]','coordinator.dataOutputs.[]',function(){
+ var datasetsForInputs = Ember.copy(this.get('coordinator.datasets'));
+ this.get('coordinator.dataOutputs').forEach((dataOutput)=>{
+ var existing = datasetsForInputs.findBy('name', dataOutput.dataset);
+ if(existing){
+ datasetsForInputs = datasetsForInputs.without(existing);
+ }
+ }.bind(this));
+ return datasetsForInputs;
+ }),
+ datasetsForOutputs : Ember.computed('coordinator.datasets.[]','coordinator.dataInputs.[]',function(){
+ var datasetsForOutputs = Ember.copy(this.get('coordinator.datasets'));
+ this.get('coordinator.dataInputs').forEach((dataInput)=>{
+ var existing = datasetsForOutputs.findBy('name', dataInput.dataset);
+ if(existing){
+ datasetsForOutputs = datasetsForOutputs.without(existing);
+ }
+ }.bind(this));
+ return datasetsForOutputs;
+ }),
+ onDestroy : function(){
+ Ember.run.cancel(this.schedulePersistWorkInProgress);
+ this.persistWorkInProgress();
+ }.on('willDestroyElement'),
+ initialize : function(){
+ var draftCoordinator = this.get('workspaceManager').restoreWorkInProgress(this.get('tabInfo.id'));
+ if(draftCoordinator){
+ this.set('coordinator', JSON.parse(draftCoordinator));
+ }else{
+ this.set('coordinator', this.createNewCoordinator());
+ }
+ this.set('timeUnitOptions',Ember.A([]));
+ this.get('timeUnitOptions').pushObject({value:'',displayName:'Select'});
+ this.get('timeUnitOptions').pushObject({value:'months',displayName:'Months'});
+ this.get('timeUnitOptions').pushObject({value:'endOfMonths',displayName:'End of Months'});
+ this.get('timeUnitOptions').pushObject({value:'days',displayName:'Days'});
+ this.get('timeUnitOptions').pushObject({value:'endOfDays',displayName:'End of Days'});
+ this.get('timeUnitOptions').pushObject({value:'hours',displayName:'Hours'});
+ this.get('timeUnitOptions').pushObject({value:'minutes',displayName:'Minutes'});
+ this.get('timeUnitOptions').pushObject({value:'cron',displayName:'Cron'});
+ this.set('coordinator.slaInfo', SlaInfo.create({}));
+
+ this.get('fileBrowser').on('fileBrowserOpened',function(context){
+ this.get('fileBrowser').setContext(context);
+ }.bind(this));
+ this.on('fileSelected',function(fileName){
+ this.set(this.get('filePathModel'), fileName);
+ }.bind(this));
+ this.set('coordinatorControls',[
+ {'name':'timeout', 'displayName':'Timeout', 'value':''},
+ {'name':'concurrency', 'displayName':'Concurrency', 'value':''},
+ {'name':'execution', 'displayName':'Execution', 'value':''},
+ {'name':'throttle', 'displayName':'Throttle', 'value':''}
+ ]);
+ this.set('timezoneList', Ember.copy(Constants.timezoneList));
+ if(Ember.isBlank(this.get('coordinator.name'))){
+ this.set('coordinator.name', Ember.copy(this.get('tabInfo.name')));
+ }
+ this.schedulePersistWorkInProgress();
+ }.on('init'),
+ conditionalDataInExists :false,
+ elementsInserted : function(){
+ this.$("input[name=dataInputType][value=" + this.get('coordinator.dataInputType') + "]").prop('checked','checked');
+ }.on('didInsertElement'),
+ observeXmlAppPath : Ember.observer('xmlAppPath', function(){
+ if(!this.get('xmlAppPath') || null === this.get('xmlAppPath')){
+ return;
+ } else {
+ this.showExistingWorkflow();
+ }
+ }),
+ observeFilePath : Ember.observer('coordinatorFilePath', function(){
+ if(!this.get('coordinatorFilePath') || null === this.get('coordinatorFilePath')){
+ return;
+ }else{
+ this.sendAction('changeFilePath', this.get('tabInfo'), this.get('coordinatorFilePath'));
+ }
+ }),
+ nameObserver : Ember.observer('coordinator.name', function(){
+ if(!this.get('coordinator')){
+ return;
+ }else if(this.get('coordinator') && Ember.isBlank(this.get('coordinator.name'))){
+ if(!this.get('clonedTabInfo')){
+ this.set('clonedTabInfo', Ember.copy(this.get('tabInfo')));
+ }
+ this.sendAction('changeTabName', this.get('tabInfo'), this.get('clonedTabInfo.name'));
+ }else{
+ this.sendAction('changeTabName', this.get('tabInfo'), this.get('coordinator.name'));
+ }
+ }),
+ schedulePersistWorkInProgress (){
+ Ember.run.later(function(){
+ this.persistWorkInProgress();
+ this.schedulePersistWorkInProgress();
+ }.bind(this), Constants.persistWorkInProgressInterval);
+ },
+ persistWorkInProgress(){
+ if(!this.get('coordinator')){
+ return;
+ }
+ var json = JSON.stringify(this.get("coordinator"));
+ this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json);
+ },
+ showExistingWorkflow : function(){
+ if(!this.get('xmlAppPath')){
+ return;
+ }
+ var workflowXmlPath = this.get("xmlAppPath"), relXmlPath = "", tempArr;
+ if(workflowXmlPath.indexOf("://") === -1 && workflowXmlPath.indexOf(":") === -1){
+ relXmlPath = workflowXmlPath;
+ } else{
+ tempArr = workflowXmlPath.split("//")[1].split("/");
+ tempArr.splice(0, 1);
+ relXmlPath = "/" + tempArr.join("/");
+ if(relXmlPath.indexOf(".xml") !== relXmlPath.length-4) {
+ if(relXmlPath.charAt(relXmlPath.length-1) !== "/"){
+ relXmlPath = relXmlPath+ "/" +"workflow.xml";
+ } else{
+ relXmlPath = relXmlPath+"workflow.xml";
+ }
+ }
+ }
+ this.importCoordinator(relXmlPath);
+ }.on('didInsertElement'),
+ createNewCoordinator(){
+ return Coordinator.create({
+ workflow : {
+ appPath : undefined,
+ configuration :{
+ property : Ember.A([])
+ }
+ },
+ frequency : {
+ type : undefined,
+ value : undefined
+ },
+ start : {
+ value : undefined,
+ displayValue : undefined,
+ type : 'date'
+ },
+ end : {
+ value : undefined,
+ displayValue : undefined,
+ type : 'date'
+ },
+ timezone : 'UTC',
+ datasets : Ember.A([]),
+ dataInputs : Ember.A([]),
+ dataOutputs : Ember.A([]),
+ dataInputType : 'simple',
+ parameters : {
+ configuration :{
+ property : Ember.A([])
+ }
+ },
+ controls : Ember.A([]),
+ slainfo : SlaInfo.create({})
+ });
+ },
+ importSampleCoordinator (){
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: "/sampledata/coordinator.xml",
+ dataType: "text",
+ cache:false,
+ success: function(data) {
+ var coordinatorXmlImporter = CoordinatorXmlImporter.create({});
+ var coordinator = coordinatorXmlImporter.importCoordinator(data);
+ deferred.resolve(coordinator);
+ }.bind(this),
+ failure : function(data){
+ deferred.reject(data);
+ }
+ });
+ return deferred;
+ },
+ importSampleWorkflow (){
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: "/sampledata/workflow.xml",
+ dataType: "text",
+ cache:false,
+ success: function(data) {
+ deferred.resolve(data);
+ }.bind(this),
+ failure : function(data){
+ deferred.reject(data);
+ }
+ });
+ return deferred;
+ },
+ importCoordinator (filePath){
+ this.set("coordinatorFilePath", filePath);
+ this.set("isImporting", false);
+ var deferred = this.readFromHdfs(filePath);
+ deferred.promise.then(function(data){
+ this.getCoordinatorFromXml(data);
+ this.set("isImporting", false);
+ }.bind(this)).catch(function(){
+ this.set("isImporting", false);
+ this.set("isImportingSuccess", false);
+ }.bind(this));
+ },
+ readFromHdfs(filePath){
+ var url = Ember.ENV.API_URL + "/readWorkflowXml?workflowXmlPath="+filePath;
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: url,
+ method: 'GET',
+ dataType: "text",
+ beforeSend: function (xhr) {
+ xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ xhr.setRequestHeader("X-Requested-By", "Ambari");
+ }
+ }).done(function(data){
+ deferred.resolve(data);
+ }).fail(function(){
+ deferred.reject();
+ });
+ return deferred;
+ },
+ getCoordinatorFromXml(coordinatorXml){
+ var coordinatorXmlImporter = CoordinatorXmlImporter.create({});
+ var coordinator = coordinatorXmlImporter.importCoordinator(coordinatorXml);
+ this.set("coordinator", coordinator);
+ this.$('input[name="dataInputType"][value="'+ coordinator.get('dataInputType')+'"]').prop('checked', true);
+ if(coordinator.get('dataInputType') === 'logical'){
+ this.set('conditionalDataInExists', true);
+ }
+ },
+ validateChildComponents(){
+ var isChildComponentsValid = true;
+ this.get('childComponents').forEach((context)=>{
+ if(context.get('validations') && context.get('validations.isInvalid')){
+ isChildComponentsValid = false;
+ context.set('showErrorMessage', true);
+ }
+ }.bind(this));
+ return isChildComponentsValid;
+ },
+ actions : {
+ registerChild(key, context){
+ this.get('childComponents').set(key, context);
+ },
+ deregisterChild(key){
+ this.get('childComponents').delete(key);
+ },
+ createDataset(){
+ this.set('datasetEditMode', false);
+ this.set('datasetCreateMode', true);
+ this.set('currentDataset',{});
+ },
+ editDataset(index){
+ this.set('datasetEditMode', true);
+ this.set('datasetCreateMode', false);
+ this.set('currentDatasetIndex', index);
+ this.set('currentDataset', Ember.copy(this.get('coordinator.datasets').objectAt(index)));
+ },
+ addDataset(){
+ this.get('coordinator.datasets').pushObject(Ember.copy(this.get('currentDataset')));
+ this.set('datasetCreateMode', false);
+ },
+ updateDataset(){
+ this.get('coordinator.datasets').replace(this.get('currentDatasetIndex'), 1, Ember.copy(this.get('currentDataset')));
+ this.set('datasetEditMode', false);
+ },
+ cancelDatasetOperation(){
+ this.set('datasetCreateMode', false);
+ this.set('datasetEditMode', false);
+ },
+ deleteDataset(index){
+ this.get('coordinator.datasets').removeAt(index);
+ if(index === this.get('currentDatasetIndex')){
+ this.set('datasetEditMode', false);
+ }
+ },
+ createDataInput(){
+ this.set('dataInputEditMode', false);
+ this.set('dataInputCreateMode', true);
+ this.set('currentDataInput', {});
+ },
+ addDataInput(){
+ this.get('coordinator.dataInputs').pushObject(Ember.copy(this.get('currentDataInput')));
+ this.set('dataInputCreateMode', false);
+ },
+ editDataInput(index){
+ this.set('dataInputCreateMode', false);
+ this.set('dataInputEditMode', true);
+ this.set('currentDataInputIndex', index);
+ this.set('currentDataInput', Ember.copy(this.get('coordinator.dataInputs').objectAt(index)));
+ },
+ updateDataInput(){
+ this.get('coordinator.dataInputs').replace(this.get('currentDataInputIndex'), 1, Ember.copy(this.get('currentDataInput')));
+ this.set('dataInputEditMode', false);
+ },
+ deleteDataInput(index){
+ this.get('coordinator.dataInputs').removeAt(index);
+ if(index === this.get('currentDataInputIndex')){
+ this.set('dataInputEditMode', false);
+ }
+ },
+ cancelDataInputOperation(){
+ this.set('dataInputEditMode', false);
+ this.set('dataInputCreateMode', false);
+ },
+ createDataOutput(){
+ this.set('dataOutputEditMode', false);
+ this.set('dataOutputCreateMode', true);
+ this.set('currentDataOutput', {});
+ },
+ addDataOutput(){
+ this.get('coordinator.dataOutputs').pushObject(Ember.copy(this.get('currentDataOutput')));
+ this.set('dataOutputCreateMode', false);
+ },
+ editDataOutput(index){
+ this.set('dataOutputCreateMode', false);
+ this.set('dataOutputEditMode', true);
+ this.set('currentDataOutputIndex', index);
+ this.set('currentDataOutput', Ember.copy(this.get('coordinator.dataOutputs').objectAt(index)));
+ },
+ updateDataOutput(){
+ this.get('coordinator.dataOutputs').replace(this.get('currentDataOutputIndex'), 1, Ember.copy(this.get('currentDataOutput')));
+ this.set('dataOutputEditMode', false);
+ },
+ deleteDataOutput(index){
+ this.get('coordinator.dataOutputs').removeAt(index);
+ if(index === this.get('currentDataOutputIndex')){
+ this.set('dataOutputEditMode', false);
+ }
+ },
+ cancelDataOutputOperation(){
+ this.set('dataOutputEditMode', false);
+ this.set('dataOutputCreateMode', false);
+ },
+ submitCoordinator(){
+ var isChildComponentsValid = this.validateChildComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ var coordGenerator=CoordinatorGenerator.create({coordinator:this.get("coordinator")});
+ var coordinatorXml=coordGenerator.process();
+ var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(coordinatorXml);
+ var configForSubmit={props:dynamicProperties,xml:coordinatorXml,params:this.get('coordinator.parameters')};
+ this.set("coordinatorConfigs", configForSubmit);
+ this.set("showingJobConfig", true);
+ },
+ closeCoordSubmitConfig(){
+ this.set("showingJobConfig", false);
+ },
+ closeFileBrowser(){
+ this.set("showingFileBrowser", false);
+ this.get('fileBrowser').getContext().trigger('fileSelected', this.get('filePath'));
+ if(this.get('coordinatorFilePath')){
+ this.importCoordinator(Ember.copy(this.get('coordinatorFilePath')));
+ this.set('coordinatorFilePath', null);
+ }
+ },
+ openFileBrowser(model, context){
+ if(!context){
+ context = this;
+ }
+ this.get('fileBrowser').trigger('fileBrowserOpened',context);
+ this.set('filePathModel', model);
+ this.set('showingFileBrowser', true);
+ },
+ createCondition(){
+ this.set('coordinator.conditionalDataInput', {type:'condition', operator:'and'});
+ this.set('conditionalDataInExists', true);
+ },
+ deleteCondition(index){
+ this.set('coordinator.conditionalDataInput', undefined);
+ this.set('conditionalDataInExists', false);
+ },
+ toggleDataTnput(type){
+ this.set('coordinator.dataInputType', type);
+ },
+ createInputLogic(){
+ this.set('coordinator.inputLogic', {type:'condition', operator:'and'});
+ this.set('inputLogicExists', true);
+ },
+ deleteInputLogic(index){
+ this.set('coordinator.inputLogic', undefined);
+ this.set('inputLogicExists', false);
+ },
+ preview(){
+ var isChildComponentsValid = this.validateChildComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.set("showingPreview", false);
+ var coordGenerator = CoordinatorGenerator.create({coordinator:this.get("coordinator")});
+ var coordinatorXml = coordGenerator.process();
+ this.set("previewXml", vkbeautify.xml(coordinatorXml));
+ this.set("showingPreview", true);
+ },
+ confirmReset(){
+ this.set('showingResetConfirmation', true);
+ },
+ resetCoordinator(){
+ this.set('coordinator', this.createNewCoordinator());
+ },
+ importCoordinatorTest(){
+ var deferred = this.importSampleCoordinator();
+ deferred.promise.then(function(data){
+ this.set("coordinator", data);
+ this.$('input[name="dataInputType"][value="'+ data.get('dataInputType')+'"]').prop('checked', true);
+ if(data.get('dataInputType') === 'logical'){
+ this.set('conditionalDataInExists', true);
+ }
+ console.error(this.get('coordinator'));
+ }.bind(this)).catch(function(e){
+ throw new Error(e);
+ });
+ },
+ openTab(type, path){
+ this.sendAction('openTab', type, path);
+ },
+ showParameterSettings(value){
+ if(this.get('coordinator.parameters') !== null){
+ this.set('parameters', Ember.copy(this.get('coordinator.parameters')));
+ }else{
+ this.set('parameters', {});
+ }
+ this.set('showParameterSettings', value);
+ },
+ closeWorkFlowParam(){
+ this.set("showParameterSettings", false);
+ },
+ saveWorkFlowParam(){
+ this.set('coordinator.parameters', Ember.copy(this.get('parameters')));
+ this.set("showParameterSettings", false);
+ },
+ showControlConfig(){
+ if(this.get('coordinator.controls')){
+ this.get('coordinatorControls').forEach((control)=>{
+ var coordControl = this.get('coordinator.controls').findBy('name', control.name);
+ if(coordControl){
+ Ember.set(control, 'value', coordControl.value);
+ }else{
+ Ember.set(control, 'value', '');
+ }
+ }, this);
+ }
+ this.set('showControlConfig', true);
+ },
+ saveCoordControls(){
+ this.get('coordinatorControls').forEach((control)=>{
+ var coordControl = this.get('coordinator.controls').findBy('name', control.name);
+ if(coordControl){
+ Ember.set(coordControl, 'value', control.value);
+ }else{
+ this.get('coordinator.controls').pushObject({'name':control.name, 'value':control.value});
+ }
+ }, this);
+ this.set('showControlConfig', false);
+ },
+ showWorkflowName(){
+ this.set('workflowName', null);
+ var deferred = this.readFromHdfs(this.get('coordinator.workflow.appPath'));
+ deferred.promise.then(function(data){
+ var x2js = new X2JS();
+ var workflowJson = x2js.xml_str2json(data);
+ this.set('workflowName', workflowJson["workflow-app"]._name);
+ }.bind(this)).catch(function(){
+ this.set('workflowName', null);
+ }.bind(this));
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
index f100808..32e2103 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
@@ -15,29 +15,39 @@
* limitations under the License.
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'credential.name': validator('presence', {
+ presence : true,
+ message : 'Required'
+ }),
+ 'credential.type': validator('presence', {
+ presence : true,
+ message : 'Required'
+ })
+});
+
+export default Ember.Component.extend(Validations, {
childComponents : new Map(),
initialize : function(){
+ if(this.get('mode') === 'create'){
+ this.set("credential", {});
+ this.set("credential.property", Ember.A([]));
+ }
+ this.initializeCredentialDetails();
if(this.get('mode') === 'edit'){
this.sendAction('register', this, this);
}
this.get('childComponents').clear();
this.set('credentialType',Ember.A([]));
- this.get('credentialType').pushObject({value:'',displayName:'Select'});
+ this.get('credentialType').pushObject({value:undefined,displayName:'Select'});
this.get('credentialType').pushObject({value:'hcat',displayName:'HCat'});
this.get('credentialType').pushObject({value:'hive2',displayName:'Hive2'});
this.get('credentialType').pushObject({value:'hbase',displayName:'HBase'});
Ember.addObserver(this, 'credential.type', this, this.credentialTypeObserver);
- this.initializeCredentialDetails();
-
- if(this.get('mode') === 'create'){
- this.set("credential", {});
- this.set("credential.property", Ember.A([]));
- }
if(this.get('credential.type') && this.get('credential.property')){
this.set('staticProps', Ember.copy(this.get('credentialDetails').findBy('name',this.get('credential.type')).staticProps));
var configProperties = this.get('credential.property');
@@ -50,37 +60,35 @@ export default Ember.Component.extend(EmberValidations, {
});
}
}.on('init'),
- rendered : function(){
- if(this.get('mode') === 'create'){
- this.$('.collapse').collapse('show');
- }else if(this.get('mode') === 'edit'){
- this.$('.collapse').collapse('hide');
+ bindStaticPropsOnEdit : function(){
+ if(this.get('mode') === 'edit'){
+ this.processStaticProps();
}
- }.on('didInsertElement'),
+ }.on('willDestroyElement'),
initializeCredentialDetails : function(){
this.set('credentialDetails', Ember.A([]));
this.get('credentialDetails').pushObject({
name:'hcat',
staticProps:
- [{name:'hcat.metastore.principal',displayName:'Hcat Metastore principal', value:'', belongsTo:'credential.property'},
- {name:'hcat.metastore.uri',displayName:'Hcat Metastore uri', value:'', belongsTo:'credential.property'}]
+ [{name:'hcat.metastore.principal',displayName:'Hcat Metastore principal', value:undefined, belongsTo:'credential.property'},
+ {name:'hcat.metastore.uri',displayName:'Hcat Metastore uri', value:undefined, belongsTo:'credential.property'}]
});
this.get('credentialDetails').pushObject({
name:'hive2',
staticProps:
- [{name:'hive2.jdbc.url',displayName:'Hive2 Jdbc Url', value:'', belongsTo:'credential.property'},
- {name:'hive2.server.principal',displayName:'Hive2 Server principal', value:'', belongsTo:'credential.property'}]
+ [{name:'hive2.jdbc.url',displayName:'Hive2 Jdbc Url', value:undefined, belongsTo:'credential.property'},
+ {name:'hive2.server.principal',displayName:'Hive2 Server principal', value:undefined, belongsTo:'credential.property'}]
});
this.get('credentialDetails').pushObject({
name:'hbase',
staticProps:
- [{name:'hadoop.security.authentication',displayName:'Hadoop security auth', value:'', belongsTo:'credential.property'},
- {name:'hbase.security.authentication',displayName:'Hbase security auth', value:'', belongsTo:'credential.property'},
- {name:'hbase.master.kerberos.principal',displayName:'Hbase Master kerberos principal', value:'', belongsTo:'credential.property'},
- {name:'hbase.regionserver.kerberos.principal',displayName:'Hbase regionserver kerberos principal', value:'', belongsTo:'credential.property'},
- {name:'hbase.zookeeper.quorum',displayName:'Hbase zookeeper quorum', value:'', belongsTo:'credential.property'},
- {name:'hadoop.rpc.protection',displayName:'Hadoop Rpc protection', value:'', belongsTo:'credential.property'},
- {name:'hbase.rpc.protection',displayName:'Hbase Rpc protection', value:'', belongsTo:'credential.property'}]
+ [{name:'hadoop.security.authentication',displayName:'Hadoop security auth', value:undefined, belongsTo:'credential.property'},
+ {name:'hbase.security.authentication',displayName:'Hbase security auth', value:undefined, belongsTo:'credential.property'},
+ {name:'hbase.master.kerberos.principal',displayName:'Hbase Master kerberos principal', value:undefined, belongsTo:'credential.property'},
+ {name:'hbase.regionserver.kerberos.principal',displayName:'Hbase regionserver kerberos principal', value:undefined, belongsTo:'credential.property'},
+ {name:'hbase.zookeeper.quorum',displayName:'Hbase zookeeper quorum', value:undefined, belongsTo:'credential.property'},
+ {name:'hadoop.rpc.protection',displayName:'Hadoop Rpc protection', value:undefined, belongsTo:'credential.property'},
+ {name:'hbase.rpc.protection',displayName:'Hbase Rpc protection', value:undefined, belongsTo:'credential.property'}]
});
},
credentialTypeObserver : function(){
@@ -97,93 +105,56 @@ export default Ember.Component.extend(EmberValidations, {
}
});
},
- resetForm : function(){
- this.set('credential', {});
- this.set('credential.property',Ember.A([]));
- this.get('staticProps').clear();
- this.initializeCredentialDetails();
- },
- validateChildrenComponents(){
- var validationPromises = [];
- var deferred = Ember.RSVP.defer();
- if(this.get('childComponents').size === 0){
- deferred.resolve(true);
- }else{
- this.get('childComponents').forEach((childComponent)=>{
- if(!childComponent.validations){
- return;
- }
- var validationDeferred = Ember.RSVP.defer();
- childComponent.validate().then(()=>{
- validationDeferred.resolve();
- }).catch((e)=>{
- validationDeferred.reject(e);
- });
- validationPromises.push(validationDeferred.promise);
- });
- Ember.RSVP.Promise.all(validationPromises).then(function(){
- deferred.resolve(true);
- }).catch(function(e){
- deferred.reject(e);
- });
+ processStaticProps() {
+ var staticProps = this.get('staticProps');
+ var index = 0;
+ if(!staticProps){
+ return;
}
- return deferred;
- },
- validations : {
- 'credential.name': {
- presence: {
- 'message' : 'Required',
+ staticProps.forEach((property)=>{
+ var existingStaticProp = this.get('credential.property').findBy('name',property.name);
+ if (existingStaticProp) {
+ Ember.set(existingStaticProp,'value',property.value);
+ index++;
+ } else {
+ var propObj = {name : property.name, value:property.value, static:true};
+ this.get('credential.property').insertAt(index++, propObj);
}
- },
- 'credential.type': {
- presence: {
- 'message' : 'Required',
+ }.bind(this));
+ },
+ validateChildrenComponents(){
+ var isChildComponentsValid = true;
+ this.get('childComponents').forEach((context)=>{
+ if(context.get('validations') && context.get('validations.isInvalid')){
+ isChildComponentsValid = false;
+ context.set('showErrorMessage', true);
}
- }
+ }.bind(this));
+ return isChildComponentsValid;
},
actions : {
register(component, context){
- if(this.get('mode') === 'edit'){
- this.sendAction('register', component, context);
- }
this.get('childComponents').set(component, context);
},
add(){
- var isFormValid = this.validateChildrenComponents();
- isFormValid.promise.then(function(){
- this.validate().then(function(){
- var staticProps = this.get('staticProps');
- var index = 0;
- staticProps.forEach((property)=>{
- var existingStaticProp = this.get('credential.property').findBy('name',property.name);
- if (existingStaticProp) {
- Ember.set(existingStaticProp,'value',property.value);
- index++;
- } else {
- var propObj = {name : property.name, value:property.value, static:true};
- this.get('credential.property').insertAt(index++, propObj);
- }
- });
- this.processMultivaluedComponents();
- this.sendAction('add',this.get('credential'));
- this.resetForm();
- }.bind(this)).catch(function(e){
- }.bind(this));
- }.bind(this)).catch(function (e) {
- });
-
- },
- delete(name){
- this.sendAction('delete',name);
- },
- togglePanel (){
- this.$('.collapse').collapse('toggle');
- if(this.$('.collapse').hasClass('in')){
- this.set('isOpen', true);
+ var isChildComponentsValid = this.validateChildrenComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.processStaticProps();
+ this.processMultivaluedComponents();
+ if(this.get('mode') === 'create'){
+ this.sendAction('add',this.get('credential'));
}else{
- this.set('isOpen', false);
+ this.sendAction('update');
}
+ },
+ cancel (){
+ this.sendAction('cancel');
+ },
+ unregister(component, context){
+ this.get('childComponents').delete(component);
}
}
-
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input-output-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input-output-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input-output-config.js
new file mode 100644
index 0000000..5ce92f5
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input-output-config.js
@@ -0,0 +1,97 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'data.name': validator('presence', {
+ presence : true
+ }),
+ 'data.dataset': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations, {
+ initialize : function(){
+ if(!this.get('data.start')){
+ this.set('data.start',{
+ type : 'date',
+ value :''
+ });
+ }
+ if(!this.get('data.end')){
+ this.set('data.end',{
+ type : 'date',
+ value :''
+ });
+ }
+ if(this.get('type') === 'output'){
+ if(!this.get('data.instance')){
+ this.set('data.instance',{
+ type : 'date',
+ value :''
+ });
+ }
+ }
+ if(this.get('type') === 'input' && !this.get('data.instances')){
+ this.set('data.instances', Ember.A([]));
+ this.set('data.isList', true);
+ }
+ this.set('childComponents', new Map());
+ }.on('init'),
+ validateChildComponents(){
+ var isChildComponentsValid = true;
+ this.get('childComponents').forEach((context)=>{
+ if(context.get('validations') && context.get('validations.isInvalid')){
+ isChildComponentsValid = false;
+ context.set('showErrorMessage', true);
+ }
+ }.bind(this));
+ return isChildComponentsValid;
+ },
+ actions : {
+ registerChild(key, context){
+ this.get('childComponents').set(key, context);
+ },
+ deregisterChild(key){
+ this.get('childComponents').delete(key);
+ },
+ onInstanceTypeChange(isList) {
+ this.set('data.isList', isList);
+ },
+ add(){
+ var isChildComponentsValid = this.validateChildComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.sendAction('add');
+ },
+ update(){
+ var isChildComponentsValid = this.validateChildComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.sendAction('update');
+ },
+ cancel(){
+ this.sendAction('cancel');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input.js
new file mode 100644
index 0000000..c484968
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/data-input.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'dataInput.dataset': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations, {
+ initialize : function(){
+ this.sendAction('register', this, this);
+ }.on('init'),
+ onDestroy : function(){
+ this.sendAction('deregister', this);
+ }.on('willDestroyElement'),
+ actions : {
+ showAdvanced(){
+ this.set('showAdvanced', true);
+ },
+ hideAdvanced(){
+ this.set('showAdvanced', false);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/dataset-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/dataset-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/dataset-config.js
new file mode 100644
index 0000000..d5253ab
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/dataset-config.js
@@ -0,0 +1,103 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { validator, buildValidations } from 'ember-cp-validations';
+import Constants from '../utils/constants';
+
+const Validations = buildValidations({
+ 'dataset.name': validator('presence', {
+ presence : true
+ }),
+ 'dataset.frequency.value': validator('presence', {
+ presence : true
+ }),
+ 'dataset.frequency.type': validator('presence', {
+ presence : true
+ }),
+ 'dataset.timezone': validator('presence', {
+ presence : true
+ }),
+ 'dataset.uriTemplate': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations, {
+ childComponents : new Map(),
+ initialize : function(){
+ if(!this.get('dataset.initialInstance')){
+ this.set('dataset.initialInstance', {
+ type : 'date',
+ value : ''
+ });
+ }
+ if(!this.get('dataset.timezone')){
+ this.set('dataset.timezone','UTC');
+ }
+ if(!this.get('dataset.frequency')){
+ this.set('dataset.frequency',{ type : undefined, value : undefined });
+ }
+ this.set('timeUnitOptions',Ember.A([]));
+ this.get('timeUnitOptions').pushObject({value:'',displayName:'Select'});
+ this.get('timeUnitOptions').pushObject({value:'months',displayName:'Months'});
+ this.get('timeUnitOptions').pushObject({value:'endOfMonths',displayName:'End of Months'});
+ this.get('timeUnitOptions').pushObject({value:'days',displayName:'Days'});
+ this.get('timeUnitOptions').pushObject({value:'endOfDays',displayName:'End of Days'});
+ this.get('timeUnitOptions').pushObject({value:'hours',displayName:'Hours'});
+ this.get('timeUnitOptions').pushObject({value:'minutes',displayName:'Minutes'});
+ this.get('timeUnitOptions').pushObject({value:'cron',displayName:'Cron'});
+ this.set('childComponents', new Map());
+ this.set('timezoneList', Ember.copy(Constants.timezoneList));
+ }.on('init'),
+ validateChildComponents(){
+ var isChildComponentsValid = true;
+ this.get('childComponents').forEach((context)=>{
+ if(context.get('validations') && context.get('validations.isInvalid')){
+ isChildComponentsValid = false;
+ context.set('showErrorMessage', true);
+ }
+ }.bind(this));
+ return isChildComponentsValid;
+ },
+ actions : {
+ registerChild(key, context){
+ this.get('childComponents').set(key, context);
+ },
+ deregisterChild(key){
+ this.get('childComponents').delete(key);
+ },
+ addDataset(){
+ var isChildComponentsValid = this.validateChildComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.sendAction('add');
+ },
+ updateDataset(){
+ var isChildComponentsValid = this.validateChildComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.sendAction('update');
+ },
+ cancelDatasetOperation(){
+ this.sendAction('cancel');
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/date-with-expr.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/date-with-expr.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/date-with-expr.js
new file mode 100644
index 0000000..dd9a9ae
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/date-with-expr.js
@@ -0,0 +1,78 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { validator, buildValidations } from 'ember-cp-validations';
+const Validations = buildValidations({
+ 'dateField.displayValue': {
+ validators: [
+ validator('presence', true),
+ validator('date', {
+ format: 'MM/DD/YYYY hh:mm A',
+ disabled(model, attribute) {
+ return model.get('dateField.type') === 'expr';
+ }
+ })
+ ]
+ },
+});
+export default Ember.Component.extend(Validations, {
+ initialize : function(){
+ this.sendAction('register', this, this);
+ }.on('init'),
+ elementsInserted : function(){
+ if(this.get('dateField.type') === 'date'){
+ this.$('input[name="'+this.get('inputName')+'"]').datetimepicker({
+ format: 'MM/DD/YYYY hh:mm A',
+ useCurrent: false,
+ showClose : true
+ });
+ }
+ Ember.addObserver(this, 'dateField.type', this, this.typeObserver);
+ Ember.addObserver(this, 'dateField.displayValue', this, this.timeObserver);
+ }.on('didInsertElement'),
+ onDestroy : function(){
+ this.sendAction('deregister', this);
+ Ember.removeObserver(this, 'dateField.type', this, this.typeObserver);
+ Ember.removeObserver(this, 'dateField.displayValue', this, this.timeObserver);
+ }.on('willDestroyElement'),
+ typeObserver : function(){
+ if(this.get('dateField.type') === 'date'){
+ this.$('input[name="'+this.get('inputName')+'"]').datetimepicker({
+ useCurrent: false,
+ showClose : true
+ });
+ this.set('dateField.displayValue', undefined);
+ }else{
+ var dateTimePicker = this.$('input[name="'+this.get('inputName')+'"]').data("DateTimePicker");
+ if(dateTimePicker){
+ dateTimePicker.destroy();
+ }
+ }
+ },
+ timeObserver : function(){
+ if(this.get('dateField.type') === 'date'){
+ var date = new Date(this.get('dateField.displayValue'));
+ if(isNaN(date.getTime())){
+ this.set('dateField.value', undefined);
+ return;
+ }
+ this.set('dateField.value', moment(date).format("YYYY-MM-DDTHH:mm")+'Z');
+ }else{
+ this.set('dateField.value', Ember.copy(this.get('dateField.displayValue')));
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
index 84d1393..e4b2224 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
@@ -17,9 +17,27 @@
import Ember from 'ember';
import {FindNodeMixin} from '../domain/findnode-mixin';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, FindNodeMixin,{
+const Validations = buildValidations({
+ 'condition': validator('presence', {
+ presence : true,
+ disabled(model) {
+ return !model.get('canValidate');
+ },
+ 'message' : 'Required',
+ dependentKeys : ['canValidate']
+ }),
+ 'targetNode': validator('presence', {
+ presence : true,
+ disabled(model) {
+ return !model.get('canValidate');
+ },
+ 'message' : 'Required',
+ dependentKeys : ['canValidate']
+ }),
+});
+export default Ember.Component.extend(Validations, FindNodeMixin,{
isInsertAction: false,
condition:"",
targetNode:"",
@@ -27,13 +45,22 @@ export default Ember.Component.extend(EmberValidations, FindNodeMixin,{
initialize : function(){
var self=this;
- this.on("showBranchOptions",function(){
+ this.on("showBranchOptions",function(node){
if (self.$("#selector-content").is(":visible")){
self.$("#selector-content").hide();
}else{
+ if (node) {
+ self.set("node", node);
+ }
self.set("isInsertAction",false);
this.set("newNodeType",null);
- this.set('descendantNodes',this.getDesendantNodes(this.get('node')));
+ var commonTarget=this.findCommonTargetNode(this.workflow.startNode,this.get('node'));
+ var descendantNodes=this.getDesendantNodes(this.get('node'));
+ if (commonTarget){
+ descendantNodes.removeObject(commonTarget);
+ descendantNodes.unshiftObject(commonTarget);
+ }
+ this.set('descendantNodes',descendantNodes);
self.$("#selector-content").show();
}
});
@@ -41,20 +68,6 @@ export default Ember.Component.extend(EmberValidations, FindNodeMixin,{
setup : function(){
this.sendAction('registerAddBranchAction',this);
}.on('didInsertElement'),
- validations : {
- 'condition': {
- presence: {
- 'if' : 'canValidate',
- 'message' : 'Required',
- }
- },
- 'targetNode': {
- presence: {
- 'if' : 'canValidate',
- 'message' : 'Required',
- }
- }
- },
actions:{
addNewNode(type){
this.set("newNodeType",type);
@@ -65,20 +78,21 @@ export default Ember.Component.extend(EmberValidations, FindNodeMixin,{
},
save(){
this.set('canValidate', true);
- this.validate().then(function(){
- this.sendAction("addDecisionBranch",{
- sourceNode: this.get("node"),
- condition:this.get("condition"),
- targetNode:this.get("targetNode"),
- newNodeType:this.get("newNodeType")
- });
- this.$("#selector-content").hide();
- this.set('canValidate', false);
- this.set('condition',"");
- this.set('targetNode',"");
- this.$('#target-node-select').prop('selectedIndex', 0);
- }.bind(this)).catch(function(e){
- }.bind(this));
+ if(this.get('validations.isInvalid')){
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.sendAction("addDecisionBranch",{
+ sourceNode: this.get("node"),
+ condition:this.get("condition"),
+ targetNode:this.get("targetNode"),
+ newNodeType:this.get("newNodeType")
+ });
+ this.$("#selector-content").hide();
+ this.set('canValidate', false);
+ this.set('condition',"");
+ this.set('targetNode',"");
+ this.$('#target-node-select').prop('selectedIndex', 0);
},
cancel(){
this.$("#selector-content").hide();
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
index 324be66..ad664d7 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-config.js
@@ -16,35 +16,20 @@
*/
import Ember from 'ember';
-import EmberValidations,{ validator } from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel': {
+ validators: [
+ validator('decission-node-validator', {
+ dependentKeys: ['actionModel.@each.condition']
+ })
+ ]
+ }
+});
+
+export default Ember.Component.extend(Validations,{
initialize : function(){
this.sendAction('register','decision',this);
- }.on('init'),
- validations: {
- 'actionModel': {
- inline : validator(function() {
- var hasDefaultCond = false;
- this.get('actionModel').forEach(function(item, index){
- if(item.condition === "default"){
- hasDefaultCond = true;
- return;
- }
- });
- if(!hasDefaultCond){
- return "Decision Should have one default condition";
- }
- var hasEmptyCond = false;
- this.get('actionModel').forEach(function(item, index){
- if(item.condition === '' || item.condition === undefined || Ember.$.trim(item.condition).length === 0){
- hasEmptyCond = true;
- return;
- }
- });
- if(hasEmptyCond){
- return "Condition cannot be blank";
- }
- })}
- }
- });
+ }.on('init')
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
new file mode 100644
index 0000000..a3d64b0
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/designer-workspace.js
@@ -0,0 +1,158 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ workspaceManager : Ember.inject.service('workspace-manager'),
+ xmlAppPath : null,
+ appPath : null,
+ type : 'wf',
+ tabId: 0,
+ hasMultitabSupport : true,
+ tabCounter : new Map(),
+ tabs : Ember.A([]),
+ currentIndex : Ember.computed('tabs.[]', function() {
+ return this.get('tabs').length > 0 ? this.get('tabs').length - 1 : 0;
+ }),
+ tabsObserver : Ember.observer('tabs.[]', function(){
+ this.get('workspaceManager').saveTabs(this.get('tabs'));
+ }),
+ initialize : function(){
+ this.get('tabCounter').set('wf', 0);
+ this.get('tabCounter').set('coord', 0);
+ this.get('tabCounter').set('bundle', 0);
+ var tabs = this.get('workspaceManager').restoreTabs();
+ if(tabs){
+ this.set('tabs', tabs);
+ }
+ this.get('tabs').forEach((tab)=>{
+ this.get('tabCounter').set(tab.type, (this.get('tabCounter').get(tab.type)) + 1);
+ }, this);
+ }.on('init'),
+ elementsInserted : function(){
+ this.$('.nav-tabs a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
+ this.get('workspaceManager').setLastActiveTab((this.$(e.target).attr('href').slice(1)));
+ }.bind(this));
+
+ if(this.get('tabs') && this.get('tabs').length > 0){
+ var lastActiveTabId = this.get('workspaceManager').getLastActiveTab();
+ var activeTab = this.get('tabs').findBy('id', lastActiveTabId);
+ if(!activeTab){
+ activeTab = this.get('tabs').objectAt(this.get('tabs').length - 1);
+ }
+ this.$('.nav-tabs a[href="#' + activeTab.id + '"]').tab('show');
+ }else{
+ if(this.get('hasMultitabSupport')){
+ this.createNewTab(this.get('type'), this.get('xmlAppPath'));
+ }else{
+ var tab = this.get('tabs').findBy('type', this.get('type'));
+ if(!tab){
+ this.createNewTab(this.get('type'), this.get('xmlAppPath'));
+ }else{
+ Ember.set(tab,'path', this.get('xmlAppPath'));
+ this.$('.nav-tabs a[href="#' + tab.id + '"]').tab('show');
+ }
+ }
+ }
+ }.on('didInsertElement'),
+ onDestroy : function(){
+ this.get('tabs').clear();
+ }.on('willDestroyElement'),
+ createNewTab : function(type, path){
+ var tab = {
+ type : type,
+ id : this.generateTabId(),
+ name : this.getDisplayName(type)+this.getTabId(type)
+ };
+ if(path){
+ tab.path = path;
+ }
+ this.$('.nav-tabs li').removeClass('active');
+ this.$('.tab-content .tab-pane').removeClass('active');
+ this.get('tabs').pushObject(tab);
+ this.set('isNew', true);
+ },
+ getDisplayName(type){
+ if(type === 'wf'){
+ return "Workflow";
+ }else if(type === 'coord'){
+ return "Coordinator";
+ }else{
+ return "Bundle";
+ }
+ },
+ getTabId(type){
+ var count = this.get('tabCounter').get(type);
+ this.get('tabCounter').set(type, ++count);
+ return count;
+ },
+ generateTabId(){
+ return 'tab-'+ Math.ceil(Math.random() * 100000);
+ },
+ actions : {
+ register(tabInfo, context){
+ var tab = this.get('tabs').findBy('id', tabInfo.id);
+ Ember.set(tab, 'context', context);
+ },
+ show(type){
+ if(this.get('hasMultitabSupport')){
+ this.createNewTab(type);
+ }else{
+ var tab = this.get('tabs').findBy('type', type);
+ if(!tab){
+ this.createNewTab(type);
+ }else{
+ this.$('.nav-tabs a[href="#' + tab.id + '"]').tab('show');
+ }
+ }
+ },
+ closeTab(index){
+ if(index < this.get('tabs').length - 1){
+ var previousTab = this.get('tabs').objectAt(index + 1);
+ this.$('.nav-tabs a[href="#'+ previousTab.id + '"]').tab('show');
+ }
+ this.get('workspaceManager').deleteWorkInProgress(this.get('tabs').objectAt(index).id);
+ this.get('tabs').removeAt(index);
+ },
+ openTab(type, path){
+ if(this.get('hasMultitabSupport')){
+ this.createNewTab(type, path);
+ }else{
+ var tab = this.get('tabs').findBy('type', type);
+ if(!tab){
+ this.createNewTab(type, path);
+ }else{
+ Ember.set(tab,'path', path);
+ this.$('.nav-tabs a[href="#' + tab.id + '"]').tab('show');
+ }
+ }
+ },
+ changeTabName(tabInfo, name){
+ var tab = this.get('tabs').findBy('id', tabInfo.id);
+ Ember.set(tab, 'name', name);
+ },
+ changeFilePath(tabInfo, path){
+ var tab = this.get('tabs').findBy('id', tabInfo.id);
+ Ember.set(tab, 'filePath', path);
+ },
+ interceptShow(tab){
+ if(tab.type === 'wf' && tab.context){
+ tab.context.resize();
+ }
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action-info.js
new file mode 100644
index 0000000..73cabac
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action-info.js
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action.js
index 1fbe4c9..e5740e3 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/distcp-action.js
@@ -16,9 +16,8 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations, {
+export default Ember.Component.extend({
fileBrowser : Ember.inject.service('file-browser'),
setUp : function(){
if(this.get('actionModel.args') === undefined){
@@ -44,9 +43,6 @@ export default Ember.Component.extend(EmberValidations, {
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
-
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action-info.js
new file mode 100644
index 0000000..73cabac
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action-info.js
@@ -0,0 +1,26 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action.js
index 357fe90..e8277f9 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/email-action.js
@@ -16,9 +16,21 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'actionModel.to': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.subject': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.body': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations, {
fileBrowser : Ember.inject.service('file-browser'),
setUp : function(){
@@ -34,23 +46,6 @@ export default Ember.Component.extend(EmberValidations, {
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.to': {
- presence: {
- 'message' : 'You need to provide a value for Email To',
- }
- },
- 'actionModel.subject': {
- presence: {
- 'message' : 'You need to provide a value for subject',
- }
- },
- 'actionModel.body': {
- presence: {
- 'message' : 'You need to provide a value for body',
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/file-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/file-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/file-config.js
index 46d30d1..c0fba4a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/file-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/file-config.js
@@ -16,9 +16,8 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations,{
+export default Ember.Component.extend({
multivalued: true,
fileBrowser : Ember.inject.service('file-browser'),
initialize : function(){
[10/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
AMBARI-18691. Improve and Update Workflow designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7c7412ed
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7c7412ed
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7c7412ed
Branch: refs/heads/branch-2.5
Commit: 7c7412ed4c350d900086cd880f1e4a5fdffc569b
Parents: 7306e0b
Author: Dipayan Bhowmick <di...@gmail.com>
Authored: Fri Oct 28 00:33:36 2016 +0530
Committer: Dipayan Bhowmick <di...@gmail.com>
Committed: Fri Oct 28 00:33:36 2016 +0530
----------------------------------------------------------------------
.../apache/oozie/ambari/view/HDFSFileUtils.java | 87 +
.../org/apache/oozie/ambari/view/JobType.java | 22 +
.../ambari/view/OozieProxyImpersonator.java | 1042 ++++++------
.../apache/oozie/ambari/view/OozieUtils.java | 71 +
.../org/apache/oozie/ambari/view/Utils.java | 154 ++
.../wfmanager/src/main/resources/ui/.jshintrc | 38 +
.../main/resources/ui/app/components/.gitkeep | 0
.../ui/app/components/archive-config.js | 3 +-
.../ui/app/components/bundle-config.js | 262 +++
.../ui/app/components/bundle-coord-config.js | 108 ++
.../ui/app/components/conditional-data-input.js | 78 +
.../ui/app/components/confirmation-dialog.js | 25 +
.../resources/ui/app/components/coord-config.js | 521 ++++++
.../ui/app/components/credentials-config.js | 175 +-
.../app/components/data-input-output-config.js | 97 ++
.../resources/ui/app/components/data-input.js | 41 +
.../ui/app/components/dataset-config.js | 103 ++
.../ui/app/components/date-with-expr.js | 78 +
.../ui/app/components/decision-add-branch.js | 78 +-
.../ui/app/components/decision-config.js | 43 +-
.../ui/app/components/designer-workspace.js | 158 ++
.../ui/app/components/distcp-action-info.js | 26 +
.../ui/app/components/distcp-action.js | 6 +-
.../ui/app/components/email-action-info.js | 26 +
.../resources/ui/app/components/email-action.js | 33 +-
.../resources/ui/app/components/file-config.js | 3 +-
.../ui/app/components/flow-designer.js | 728 +++++----
.../ui/app/components/fs-action-info.js | 26 +
.../resources/ui/app/components/fs-action.js | 64 +-
.../ui/app/components/fsaction-info.js | 21 +
.../resources/ui/app/components/hdfs-browser.js | 5 +-
.../ui/app/components/hive-action-info.js | 26 +
.../resources/ui/app/components/hive-action.js | 38 +-
.../ui/app/components/hive2-action-info.js | 25 +
.../resources/ui/app/components/hive2-action.js | 44 +-
.../resources/ui/app/components/info-header.js | 26 +
.../ui/app/components/instance-list-config.js | 54 +
.../ui/app/components/java-action-info.js | 25 +
.../resources/ui/app/components/java-action.js | 25 +-
.../resources/ui/app/components/job-config.js | 303 ++++
.../resources/ui/app/components/job-details.js | 391 ++++-
.../ui/app/components/killnode-config.js | 29 +
.../ui/app/components/killnode-manager.js | 62 +
.../ui/app/components/map-red-action.js | 6 +-
.../ui/app/components/map-reduce-action-info.js | 25 +
.../ui/app/components/name-value-config.js | 7 +-
.../ui/app/components/name-value-info.js | 21 +
.../ui/app/components/named-properties.js | 25 +-
.../ui/app/components/pig-action-info.js | 25 +
.../resources/ui/app/components/pig-action.js | 16 +-
.../ui/app/components/prepare-config-fs.js | 7 +-
.../ui/app/components/prepare-config-info.js | 21 +
.../ui/app/components/prepare-config.js | 3 +-
.../ui/app/components/preview-dialog.js | 20 +
.../ui/app/components/property-value-config.js | 21 +
.../main/resources/ui/app/components/save-wf.js | 170 ++
.../ui/app/components/shell-action-info.js | 25 +
.../resources/ui/app/components/shell-action.js | 20 +-
.../resources/ui/app/components/sla-info.js | 148 +-
.../ui/app/components/spark-action-info.js | 25 +
.../resources/ui/app/components/spark-action.js | 59 +-
.../ui/app/components/sqoop-action-info.js | 25 +
.../resources/ui/app/components/sqoop-action.js | 5 +-
.../ui/app/components/ssh-action-info.js | 25 +
.../resources/ui/app/components/ssh-action.js | 24 +-
.../app/components/sub-workflow-action-info.js | 25 +
.../resources/ui/app/components/sub-workflow.js | 17 +-
.../ui/app/components/transition-config.js | 44 +-
.../ui/app/components/workflow-action-editor.js | 58 +-
.../ui/app/components/workflow-actions.js | 7 +
.../ui/app/components/workflow-credentials.js | 65 +-
.../app/components/workflow-job-action-info.js | 22 +
.../ui/app/components/workflow-node.js | 9 +
.../ui/app/components/workflow-parameters.js | 64 +-
.../resources/ui/app/components/workflow-sla.js | 15 +-
.../main/resources/ui/app/controllers/.gitkeep | 0
.../main/resources/ui/app/controllers/design.js | 5 -
.../ui/app/domain/action-type-resolver.js | 62 +
.../ui/app/domain/actionjob_hanlder.js | 1 +
.../app/domain/bundle/bundle-xml-generator.js | 55 +
.../ui/app/domain/bundle/bundle-xml-importer.js | 87 +
.../resources/ui/app/domain/bundle/bundle.js | 22 +
.../coordinator/coordinator-xml-generator.js | 204 +++
.../coordinator/coordinator-xml-importer.js | 272 ++++
.../ui/app/domain/coordinator/coordinator.js | 22 +
.../ui/app/domain/cytoscape-flow-renderer.js | 348 ++++
.../resources/ui/app/domain/cytoscape-style.js | 123 ++
.../ui/app/domain/default-layout-manager.js | 10 +-
.../resources/ui/app/domain/findnode-mixin.js | 113 +-
.../src/main/resources/ui/app/domain/id-gen.js | 4 +
.../ui/app/domain/jsplumb-flow-renderer.js | 194 +++
.../resources/ui/app/domain/mapping-utils.js | 31 +-
.../resources/ui/app/domain/node-factory.js | 10 +-
.../resources/ui/app/domain/node-handler.js | 49 +-
.../src/main/resources/ui/app/domain/node.js | 3 +-
.../main/resources/ui/app/domain/sla-info.js | 38 +-
.../main/resources/ui/app/domain/transition.js | 5 +-
.../ui/app/domain/workflow-importer.js | 8 +-
.../ui/app/domain/workflow-json-importer.js | 92 ++
.../ui/app/domain/workflow-path-util.js | 73 +
.../ui/app/domain/workflow-xml-generator.js | 1 -
.../main/resources/ui/app/domain/workflow.js | 114 +-
.../ui/app/domain/workflow_xml_mapper.js | 5 +-
.../src/main/resources/ui/app/helpers/.gitkeep | 0
.../src/main/resources/ui/app/index.html | 9 +
.../src/main/resources/ui/app/routes/.gitkeep | 0
.../main/resources/ui/app/routes/dashboard.js | 10 +-
.../src/main/resources/ui/app/routes/design.js | 38 +-
.../ui/app/services/workflow-clipboard.js | 34 +
.../ui/app/services/workspace-manager.js | 62 +
.../src/main/resources/ui/app/styles/app.less | 1497 ++++++++++++++++++
.../ui/app/templates/components/.gitkeep | 0
.../app/templates/components/bundle-config.hbs | 129 ++
.../components/bundle-coord-config.hbs | 58 +
.../templates/components/bundle-job-details.hbs | 17 +-
.../components/conditional-data-input.hbs | 64 +
.../components/confirmation-dialog.hbs | 34 +
.../app/templates/components/coord-config.hbs | 352 ++++
.../templates/components/coord-job-details.hbs | 17 +-
.../templates/components/credentials-config.hbs | 33 +-
.../components/data-input-output-config.hbs | 68 +
.../ui/app/templates/components/data-input.hbs | 40 +
.../app/templates/components/dataset-config.hbs | 70 +
.../app/templates/components/date-with-expr.hbs | 41 +
.../components/decision-add-branch.hbs | 4 +-
.../templates/components/decision-config.hbs | 2 +-
.../templates/components/designer-workspace.hbs | 106 ++
.../templates/components/distcp-action-info.hbs | 35 +
.../templates/components/email-action-info.hbs | 28 +
.../app/templates/components/email-action.hbs | 10 +-
.../ui/app/templates/components/field-error.hbs | 3 +
.../app/templates/components/flow-designer.hbs | 300 ++--
.../app/templates/components/fs-action-info.hbs | 33 +
.../ui/app/templates/components/fs-action.hbs | 3 +-
.../app/templates/components/fsaction-info.hbs | 39 +
.../app/templates/components/hdfs-browser.hbs | 2 +-
.../templates/components/hive-action-info.hbs | 47 +
.../ui/app/templates/components/hive-action.hbs | 6 +-
.../templates/components/hive2-action-info.hbs | 49 +
.../app/templates/components/hive2-action.hbs | 6 +-
.../ui/app/templates/components/info-header.hbs | 18 +
.../components/instance-list-config.hbs | 35 +
.../templates/components/java-action-info.hbs | 52 +
.../ui/app/templates/components/java-action.hbs | 4 +-
.../ui/app/templates/components/job-config.hbs | 126 ++
.../ui/app/templates/components/job-details.hbs | 2 +-
.../templates/components/killnode-config.hbs | 67 +
.../templates/components/killnode-manager.hbs | 69 +
.../components/map-reduce-action-info.hbs | 41 +
.../templates/components/name-value-info.hbs | 22 +
.../templates/components/named-properties.hbs | 2 +-
.../templates/components/pig-action-info.hbs | 47 +
.../ui/app/templates/components/pig-action.hbs | 2 +-
.../templates/components/prepare-config-fs.hbs | 46 +-
.../components/prepare-config-info.hbs | 22 +
.../app/templates/components/preview-dialog.hbs | 33 +
.../components/property-value-config.hbs | 22 +
.../ui/app/templates/components/save-wf.hbs | 79 +
.../templates/components/shell-action-info.hbs | 48 +
.../app/templates/components/shell-action.hbs | 4 +-
.../ui/app/templates/components/sla-info.hbs | 17 +-
.../templates/components/spark-action-info.hbs | 46 +
.../app/templates/components/spark-action.hbs | 6 +-
.../templates/components/sqoop-action-info.hbs | 41 +
.../templates/components/ssh-action-info.hbs | 32 +
.../ui/app/templates/components/ssh-action.hbs | 4 +-
.../components/sub-workflow-action-info.hbs | 29 +
.../app/templates/components/sub-workflow.hbs | 2 +-
.../templates/components/transition-config.hbs | 23 +-
.../templates/components/version-settings.hbs | 2 +-
.../templates/components/workflow-actions.hbs | 5 +
.../templates/components/workflow-config.hbs | 2 +-
.../components/workflow-credentials.hbs | 34 +-
.../components/workflow-job-action-info.hbs | 80 +
.../components/workflow-job-details.hbs | 158 +-
.../app/templates/components/workflow-node.hbs | 3 +-
.../components/workflow-parameters.hbs | 23 +-
.../resources/ui/app/templates/dashboard.hbs | 2 +-
.../main/resources/ui/app/templates/design.hbs | 2 +-
.../main/resources/ui/app/utils/constants.js | 43 +-
.../app/validators/decission-node-validator.js | 58 +
.../app/validators/duplicate-data-node-name.js | 60 +
.../validators/duplicate-flattened-node-name.js | 66 +
.../app/validators/duplicate-kill-node-name.js | 58 +
.../ui/app/validators/fs-action-validator.js | 76 +
.../ui/app/validators/job-params-validator.js | 54 +
.../ui/app/validators/operand-length.js | 46 +
.../resources/ui/app/validators/unique-name.js | 59 +
.../wfmanager/src/main/resources/ui/bower.json | 5 +-
.../src/main/resources/ui/ember-cli-build.js | 10 +
.../hdfs-directory-viewer/addon/.gitkeep | 0
.../hdfs-directory-viewer/app/.gitkeep | 0
.../tests/dummy/app/components/.gitkeep | 0
.../tests/dummy/app/controllers/.gitkeep | 0
.../tests/dummy/app/helpers/.gitkeep | 0
.../tests/dummy/app/models/.gitkeep | 0
.../tests/dummy/app/routes/.gitkeep | 0
.../dummy/app/templates/components/.gitkeep | 0
.../tests/integration/.gitkeep | 0
.../hdfs-directory-viewer/tests/unit/.gitkeep | 0
.../hdfs-directory-viewer/vendor/.gitkeep | 0
.../resources/ui/mock-service/mock-server.js | 52 +
.../main/resources/ui/mock-service/mockData.js | 316 ++++
.../src/main/resources/ui/package.json | 18 +-
.../main/resources/ui/public/assets/favicon.ico | Bin 0 -> 1150 bytes
.../main/resources/ui/public/assets/join.png | Bin 0 -> 331 bytes
.../main/resources/ui/public/assets/logo.png | Bin 0 -> 4568 bytes
.../main/resources/ui/public/assets/play.png | Bin 0 -> 1164 bytes
.../main/resources/ui/public/assets/sitemap.png | Bin 0 -> 317 bytes
.../main/resources/ui/public/assets/stop.png | Bin 0 -> 1164 bytes
.../src/main/resources/ui/public/loader.gif | Bin 0 -> 42435 bytes
.../resources/ui/public/sampledata/bundle.xml | 32 +
.../ui/public/sampledata/coordinator.xml | 113 ++
.../resources/ui/tests/integration/.gitkeep | 0
.../components/bundle-config-test.js | 40 +
.../components/bundle-coord-config-test.js | 40 +
.../components/conditional-data-input-test.js | 40 +
.../components/confirmation-dialog-test.js | 40 +
.../integration/components/coord-config-test.js | 40 +
.../components/data-input-output-config-test.js | 40 +
.../integration/components/data-input-test.js | 40 +
.../components/dataset-config-test.js | 40 +
.../components/date-with-expr-test.js | 40 +
.../components/designer-workspace-test.js | 40 +
.../components/distcp-action-info-test.js | 41 +
.../components/email-action-info-test.js | 41 +
.../components/fs-action-info-test.js | 41 +
.../components/fsaction-info-test.js | 41 +
.../components/hive-action-info-test.js | 41 +
.../components/hive2-action-info-test.js | 41 +
.../integration/components/info-header-test.js | 41 +
.../components/instance-list-config-test.js | 41 +
.../components/java-action-info-test.js | 41 +
.../integration/components/job-config-test.js | 41 +
.../components/killnode-config-test.js | 41 +
.../components/killnode-manager-test.js | 41 +
.../components/map-reduce-action-info-test.js | 41 +
.../components/name-value-info-test.js | 41 +
.../components/pig-action-info-test.js | 41 +
.../components/prepare-config-info-test.js | 41 +
.../components/preview-dialog-test.js | 40 +
.../components/property-value-config-test.js | 41 +
.../integration/components/save-wf-test.js | 40 +
.../components/shell-action-info-test.js | 41 +
.../components/spark-action-info-test.js | 41 +
.../components/sqoop-action-info-test.js | 41 +
.../components/ssh-action-info-test.js | 41 +
.../components/sub-workflow-action-info-test.js | 41 +
.../src/main/resources/ui/tests/unit/.gitkeep | 0
.../unit/services/workflow-clipboard-test.js | 29 +
.../unit/services/workspace-manager-test.js | 29 +
.../validators/decission-node-validator-test.js | 26 +
.../validators/duplicate-data-node-name-test.js | 27 +
.../duplicate-flattened-node-name-test.js | 27 +
.../validators/duplicate-kill-node-name-test.js | 27 +
.../unit/validators/fs-action-validator-test.js | 26 +
.../validators/job-params-validator-test.js | 26 +
.../unit/validators/operand-length-test.js | 27 +
.../tests/unit/validators/unique-name-test.js | 27 +
259 files changed, 13407 insertions(+), 1980 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java
new file mode 100644
index 0000000..58c3980
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/HDFSFileUtils.java
@@ -0,0 +1,87 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie.ambari.view;
+
+import java.io.IOException;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.utils.hdfs.HdfsApi;
+import org.apache.ambari.view.utils.hdfs.HdfsUtil;
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FSDataOutputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class HDFSFileUtils {
+ private final static Logger LOGGER = LoggerFactory
+ .getLogger(HDFSFileUtils.class);
+ private ViewContext viewContext;
+
+ public HDFSFileUtils(ViewContext viewContext) {
+ super();
+ this.viewContext = viewContext;
+ }
+ public boolean fileExists(String path) {
+ boolean fileExists;
+ try {
+ fileExists = getHdfsgetApi().exists(path);
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ throw new RuntimeException(e);
+ } catch (InterruptedException e) {
+ LOGGER.error(e.getMessage(), e);
+ throw new RuntimeException(e);
+ }
+ LOGGER.info("FILE exists for [" + path + "] returned [" + fileExists
+ + "]");
+ return fileExists;
+ }
+ public FSDataInputStream read(String filePath)throws IOException{
+ FSDataInputStream is;
+ try {
+ is = getHdfsgetApi().open(filePath);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ return is;
+ }
+ public String createWorkflowFile( String workflowFile,String postBody,
+ boolean overwrite) throws IOException {
+ FSDataOutputStream fsOut;
+ try {
+ fsOut = getHdfsgetApi().create(workflowFile,
+ overwrite);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ fsOut.write(postBody.getBytes());
+ fsOut.close();
+ return workflowFile;
+ }
+ private HdfsApi getHdfsgetApi() {
+ try {
+ return HdfsUtil.connectToHDFSApi(viewContext);
+ } catch (Exception ex) {
+ LOGGER.error("Error in getting HDFS Api", ex);
+ throw new RuntimeException(
+ "HdfsApi connection failed. Check \"webhdfs.url\" property",
+ ex);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/JobType.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/JobType.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/JobType.java
new file mode 100644
index 0000000..5a47b68
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/JobType.java
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie.ambari.view;
+
+public enum JobType {
+ WORKFLOW, COORDINATOR, BUNDLE
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
index 3ed6352..0533f04 100644
--- a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
@@ -20,14 +20,10 @@ package org.apache.oozie.ambari.view;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.StringReader;
-import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
@@ -48,522 +44,550 @@ import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import javax.ws.rs.core.UriInfo;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.TransformerFactoryConfigurationError;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
import org.apache.ambari.view.URLStreamProvider;
import org.apache.ambari.view.ViewContext;
-import org.apache.ambari.view.utils.ambari.AmbariApi;
-import org.apache.ambari.view.utils.hdfs.HdfsApi;
-import org.apache.ambari.view.utils.hdfs.HdfsUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.hadoop.fs.FSDataInputStream;
-import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.security.AccessControlException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
+
+import com.google.inject.Singleton;
/**
* This is a class used to bridge the communication between the and the Oozie
* API executing inside ambari.
*/
+@Singleton
public class OozieProxyImpersonator {
-
- private static final String OOZIE_WF_APPLICATION_PATH_CONF_KEY = "oozie.wf.application.path";
- private static final String OOZIE_WF_RERUN_FAILNODES_CONF_KEY = "oozie.wf.rerun.failnodes";
- private static final String OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY = "oozie.use.system.libpath";
- private static final String XML_INDENT_SPACES = "4";
- private static final String XML_INDENT_AMT_PROP_NAME = "{http://xml.apache.org/xslt}indent-amount";
- private ViewContext viewContext;
- private AmbariApi ambariApi;
- private HdfsApi _hdfsApi = null;
-
- private static final String USER_NAME_HEADER = "user.name";
- private static final String USER_OOZIE_SUPER = "oozie";
- private static final String DO_AS_HEADER = "doAs";
-
- private static final String SERVICE_URI_PROP = "oozie.service.uri";
- private static final String DEFAULT_SERVICE_URI = "http://sandbox.hortonworks.com:11000/oozie";
-
- private final static Logger LOGGER = LoggerFactory
- .getLogger(OozieProxyImpersonator.class);
-
- @Inject
- public OozieProxyImpersonator(ViewContext viewContext) {
- this.viewContext = viewContext;
- this.ambariApi = new AmbariApi(viewContext);
- LOGGER.info(String.format(
- "OozieProxyImpersonator initialized for instance: %s",
- viewContext.getInstanceName()));
- }
-
- @Path("/fileServices")
- public FileServices fileServices() {
- return new FileServices(viewContext);
- }
-
- @POST
- @Path("/submitWorkflow")
- @Consumes({MediaType.TEXT_PLAIN + "," + MediaType.TEXT_XML})
- public Response submitWorkflow(String postBody, @Context HttpHeaders headers,
- @Context UriInfo ui, @QueryParam("app.path") String appPath,
- @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite) {
- LOGGER.info("submit workflow job called");
- try {
- if (StringUtils.isEmpty(appPath)) {
- throw new RuntimeException("app path can't be empty.");
- }
- appPath = appPath.trim();
- if (!overwrite) {
- boolean fileExists = getHdfsgetApi().exists(appPath);
- LOGGER.info("FILE exists for [" + appPath + "] returned [" + fileExists
- + "]");
- if (fileExists) {
- HashMap<String, String> resp = new HashMap<String, String>();
- resp.put("status", "workflow.folder.exists");
- resp.put("message", "Workflow Folder exists");
- return Response.status(Response.Status.BAD_REQUEST).entity(resp)
- .build();
- }
- }
- String workflowFile = null;
- if (appPath.endsWith(".xml")) {
- workflowFile = appPath;
- } else {
- workflowFile = appPath + (appPath.endsWith("/") ? "" : "/")
- + "workflow.xml";
- }
- postBody = formatXml(postBody);
- try {
- String filePath = createWorkflowFile(postBody, workflowFile, overwrite);
- LOGGER.info(String.format("submit workflow job done. filePath=[%s]",
- filePath));
- } catch (org.apache.hadoop.security.AccessControlException ace) {
- HashMap<String, String> resp = new HashMap<String, String>();
- resp.put("status", "workflow.oozie.error");
- resp.put("message", "You dont seem to have access to folder path.");
- return Response.status(Response.Status.BAD_REQUEST).entity(resp)
- .build();
- }
-
- String response = submitWorkflowJobToOozie(headers, appPath,
- ui.getQueryParameters());
- if (response != null && response.trim().startsWith("{")) {
- // dealing with oozie giving error but with 200 response.
- return Response.status(Response.Status.OK).entity(response).build();
- } else {
- HashMap<String, String> resp = new HashMap<String, String>();
- resp.put("status", "workflow.oozie.error");
- resp.put("message", response);
- return Response.status(Response.Status.BAD_REQUEST).entity(resp)
- .build();
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } catch (Exception e) {
- LOGGER.error("Error in submit workflow", e);
- throw new RuntimeException(e);
- }
- }
-
- @GET
- @Path("/readWorkflowXml")
- public Response readWorkflowXxml(
- @QueryParam("workflowXmlPath") String workflowPath) {
- if (StringUtils.isEmpty(workflowPath)) {
- throw new RuntimeException("workflowXmlPath can't be empty.");
- }
- try {
- final FSDataInputStream is = getHdfsgetApi().open(workflowPath);
- StreamingOutput streamer = new StreamingOutput() {
-
- @Override
- public void write(OutputStream os) throws IOException,
- WebApplicationException {
- IOUtils.copy(is, os);
- is.close();
- os.close();
- }
- };
- return Response.ok(streamer).status(200).build();
- } catch (org.apache.hadoop.security.AccessControlException ace) {
- HashMap<String, String> resp = new HashMap<String, String>();
- resp.put("status", "workflow.oozie.error");
- resp.put("message", "Access denied to file path");
- return Response.status(Response.Status.FORBIDDEN).entity(resp).build();
- } catch (IOException e) {
- LOGGER.error("Error in read worfklow file", e);
- throw new RuntimeException(e);
- } catch (InterruptedException e) {
- LOGGER.error("Error in read worfklow file", e);
- throw new RuntimeException(e);
- }
- }
-
- @GET
- @Path("/getDag")
- @Produces("image/png")
- public Response submitWorkflow(@Context HttpHeaders headers,
- @Context UriInfo ui, @QueryParam("jobid") String jobid) {
- String imgUrl = getServiceUri() + "/v2/job/" + jobid + "?show=graph";
- Map<String, String> newHeaders = getHeaders(headers);
- final InputStream is = readFromOozie(headers, imgUrl, HttpMethod.GET, null,
- newHeaders);
- StreamingOutput streamer = new StreamingOutput() {
-
- @Override
- public void write(OutputStream os) throws IOException,
- WebApplicationException {
- IOUtils.copy(is, os);
- is.close();
- os.close();
- }
-
- };
- return Response.ok(streamer).status(200).build();
- }
-
- @GET
- @Path("/{path: .*}")
- public Response handleGet(@Context HttpHeaders headers, @Context UriInfo ui) {
- try {
- String serviceURI = buildURI(ui);
- return consumeService(headers, serviceURI, HttpMethod.GET, null);
- } catch (Exception ex) {
- LOGGER.error("Error in GET proxy", ex);
- return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
- .build();
- }
- }
-
- @POST
- @Path("/{path: .*}")
- public Response handlePost(String xml, @Context HttpHeaders headers, @Context UriInfo ui) {
- try {
- String serviceURI = buildURI(ui);
- return consumeService(headers, serviceURI, HttpMethod.POST, xml);
- } catch (Exception ex) {
- LOGGER.error("Error in POST proxy", ex);
- return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
- .build();
- }
- }
-
- @DELETE
- @Path("/{path: .*}")
- public Response handleDelete(@Context HttpHeaders headers, @Context UriInfo ui) {
- try {
- String serviceURI = buildURI(ui);
- return consumeService(headers, serviceURI, HttpMethod.POST, null);
- } catch (Exception ex) {
- LOGGER.error("Error in DELETE proxy", ex);
- return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
- .build();
- }
- }
-
- @PUT
- @Path("/{path: .*}")
- public Response handlePut(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
-
- try {
- String serviceURI = buildURI(ui);
- return consumeService(headers, serviceURI, HttpMethod.PUT, body);
- } catch (Exception ex) {
- LOGGER.error("Error in PUT proxy", ex);
- return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
- .build();
- }
- }
-
- private String submitWorkflowJobToOozie(HttpHeaders headers, String filePath,
- MultivaluedMap<String, String> queryParams) {
- String nameNode = "hdfs://" + viewContext.getCluster().getConfigurationValue("hdfs-site", "dfs.namenode.rpc-address");
-
- if (!queryParams.containsKey("config.nameNode")) {
- ArrayList<String> nameNodes = new ArrayList<String>();
- LOGGER.info("Namenode===" + nameNode);
- nameNodes.add(nameNode);
- queryParams.put("config.nameNode", nameNodes);
- }
-
- HashMap<String, String> workflowConigs = new HashMap<String, String>();
- if (queryParams.containsKey("resourceManager")
- && "useDefault".equals(queryParams.getFirst("resourceManager"))) {
- String jobTrackerNode = viewContext.getCluster().getConfigurationValue(
- "yarn-site", "yarn.resourcemanager.address");
- LOGGER.info("jobTrackerNode===" + jobTrackerNode);
- workflowConigs.put("resourceManager", jobTrackerNode);
- workflowConigs.put("jobTracker", jobTrackerNode);
- }
- if (queryParams != null) {
- for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
- if (entry.getKey().startsWith("config.")) {
- if (entry.getValue() != null && entry.getValue().size() > 0) {
- workflowConigs.put(entry.getKey().substring(7), entry.getValue()
- .get(0));
- }
- }
- }
- }
-
- if (queryParams.containsKey("oozieconfig.useSystemLibPath")) {
- String useSystemLibPath = queryParams
- .getFirst("oozieconfig.useSystemLibPath");
- workflowConigs.put(OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY, useSystemLibPath);
- } else {
- workflowConigs.put(OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY, "true");
- }
- if (queryParams.containsKey("oozieconfig.rerunOnFailure")) {
- String rerunFailnodes = queryParams
- .getFirst("oozieconfig.rerunOnFailure");
- workflowConigs.put(OOZIE_WF_RERUN_FAILNODES_CONF_KEY, rerunFailnodes);
- } else {
- workflowConigs.put(OOZIE_WF_RERUN_FAILNODES_CONF_KEY, "true");
- }
-
- workflowConigs.put("user.name", viewContext.getUsername());
- workflowConigs.put(OOZIE_WF_APPLICATION_PATH_CONF_KEY, nameNode + filePath);
- String configXMl = generateConigXml(workflowConigs);
- LOGGER.info("Config xml==" + configXMl);
- HashMap<String, String> customHeaders = new HashMap<String, String>();
- customHeaders.put("Content-Type", "application/xml;charset=UTF-8");
- Response serviceResponse = consumeService(headers, getServiceUri()
- + "/v2/jobs", HttpMethod.POST, configXMl, customHeaders);
-
- LOGGER
- .info("REsp from oozie status entity==" + serviceResponse.getEntity());
- if (serviceResponse.getEntity() instanceof String) {
- return (String) serviceResponse.getEntity();
- } else {
- return "success";
- }
-
- }
-
- private String createWorkflowFile(String postBody, String workflowFile, boolean overwrite) throws IOException, InterruptedException {
- FSDataOutputStream fsOut = getHdfsgetApi().create(workflowFile, overwrite);
- fsOut.write(postBody.getBytes());
- fsOut.close();
- return workflowFile;
- }
-
- private String buildURI(UriInfo ui) {
- String uiURI = ui.getAbsolutePath().getPath();
- int index = uiURI.indexOf("proxy/") + 5;
- uiURI = uiURI.substring(index);
- String serviceURI = getServiceUri();
- serviceURI += uiURI;
-
- MultivaluedMap<String, String> parameters = ui.getQueryParameters();
- StringBuilder urlBuilder = new StringBuilder(serviceURI);
- boolean firstEntry = true;
- for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
- if ("user.name".equals(entry.getKey())) {
- ArrayList<String> vals = new ArrayList<String>();
- vals.add(viewContext.getUsername());
- entry.setValue(vals);
- }
- if (firstEntry) {
- urlBuilder.append("?");
- } else {
- urlBuilder.append("&");
- }
- boolean firstVal = true;
- for (String val : entry.getValue()) {
- urlBuilder.append(firstVal ? "" : "&").append(entry.getKey())
- .append("=").append(val);
- firstVal = false;
- }
- firstEntry = false;
- }
- return urlBuilder.toString();
- }
-
- private String getServiceUri() {
- String serviceURI = viewContext.getProperties().get(SERVICE_URI_PROP) != null ? viewContext
- .getProperties().get(SERVICE_URI_PROP) : DEFAULT_SERVICE_URI;
- return serviceURI;
- }
-
- public Response consumeService(HttpHeaders headers, String urlToRead,
- String method, String body, Map<String, String> customHeaders) {
- Response response = null;
- InputStream stream = readFromOozie(headers, urlToRead, method, body,
- customHeaders);
- String stringResponse = null;
- try {
- stringResponse = IOUtils.toString(stream);
- } catch (IOException e) {
- LOGGER.error("Error while converting stream to string", e);
- throw new RuntimeException(e);
- }
- if (stringResponse.contains(Response.Status.BAD_REQUEST.name())) {
- response = Response.status(Response.Status.BAD_REQUEST)
- .entity(stringResponse).type(MediaType.TEXT_PLAIN).build();
- } else {
- response = Response.status(Response.Status.OK).entity(stringResponse)
- .type(deduceType(stringResponse)).build();
- }
- return response;
- }
-
- private InputStream readFromOozie(HttpHeaders headers, String urlToRead,
- String method, String body, Map<String, String> customHeaders) {
- URLStreamProvider streamProvider = viewContext.getURLStreamProvider();
- Map<String, String> newHeaders = getHeaders(headers);
- newHeaders.put(USER_NAME_HEADER, USER_OOZIE_SUPER);
-
- newHeaders.put(DO_AS_HEADER, viewContext.getUsername());
- newHeaders.put("Accept", MediaType.APPLICATION_JSON);
- if (customHeaders != null) {
- newHeaders.putAll(customHeaders);
- }
- LOGGER.info(String.format("Proxy request for url: [%s] %s", method,
- urlToRead));
- boolean securityEnabled = isSecurityEnabled();
- LOGGER.debug(String.format("IS security enabled:[%b]", securityEnabled));
- InputStream stream = null;
- try {
- if (securityEnabled) {
- stream = streamProvider.readAsCurrent(urlToRead, method, body, newHeaders);
-
- } else {
- stream = streamProvider.readFrom(urlToRead, method, body, newHeaders);
- }
- } catch (IOException e) {
- LOGGER.error("error talking to oozie", e);
- throw new RuntimeException(e);
- }
- return stream;
- }
-
- public Response consumeService(HttpHeaders headers, String urlToRead,
- String method, String body) throws Exception {
- return consumeService(headers, urlToRead, method, body, null);
- }
-
- public Map<String, String> getHeaders(HttpHeaders headers) {
- MultivaluedMap<String, String> requestHeaders = headers.getRequestHeaders();
- Set<Entry<String, List<String>>> headerEntrySet = requestHeaders.entrySet();
- HashMap<String, String> headersMap = new HashMap<String, String>();
- for (Entry<String, List<String>> headerEntry : headerEntrySet) {
- String key = headerEntry.getKey();
- List<String> values = headerEntry.getValue();
- headersMap.put(key, strJoin(values, ","));
- }
- return headersMap;
- }
-
- public String strJoin(List<String> strings, String separator) {
- StringBuilder stringBuilder = new StringBuilder();
- for (int i = 0, il = strings.size(); i < il; i++) {
- if (i > 0) {
- stringBuilder.append(separator);
- }
- stringBuilder.append(strings.get(i));
- }
- return stringBuilder.toString();
- }
-
- private MediaType deduceType(String stringResponse) {
- if (stringResponse.startsWith("{")) {
- return MediaType.APPLICATION_JSON_TYPE;
- } else if (stringResponse.startsWith("<")) {
- return MediaType.TEXT_XML_TYPE;
- } else {
- return MediaType.APPLICATION_JSON_TYPE;
- }
- }
-
- private HdfsApi getHdfsgetApi() {
- if (_hdfsApi == null) {
- try {
- _hdfsApi = HdfsUtil.connectToHDFSApi(viewContext);
- } catch (Exception ex) {
- LOGGER.error("Error in getting HDFS Api", ex);
- throw new RuntimeException("HdfsApi connection failed. Check \"webhdfs.url\" property", ex);
- }
- }
- return _hdfsApi;
- }
-
- private String generateConigXml(Map<String, String> map) {
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- DocumentBuilder db;
- try {
- db = dbf.newDocumentBuilder();
- Document doc = db.newDocument();
- Element configElement = doc.createElement("configuration");
- doc.appendChild(configElement);
- for (Map.Entry<String, String> entry : map.entrySet()) {
- Element propElement = doc.createElement("property");
- configElement.appendChild(propElement);
- Element nameElem = doc.createElement("name");
- nameElem.setTextContent(entry.getKey());
- Element valueElem = doc.createElement("value");
- valueElem.setTextContent(entry.getValue());
- propElement.appendChild(nameElem);
- propElement.appendChild(valueElem);
- }
- DOMSource domSource = new DOMSource(doc);
- StringWriter writer = new StringWriter();
- StreamResult result = new StreamResult(writer);
- TransformerFactory tf = TransformerFactory.newInstance();
- Transformer transformer = tf.newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer
- .setOutputProperty(XML_INDENT_AMT_PROP_NAME, XML_INDENT_SPACES);
- transformer.transform(domSource, result);
- return writer.toString();
- } catch (ParserConfigurationException | TransformerException e) {
- LOGGER.error("error in generating config xml", e);
- throw new RuntimeException(e);
- }
-
- }
-
- private String formatXml(String xml) {
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- try {
- DocumentBuilder db = dbf.newDocumentBuilder();
- StreamResult result = new StreamResult(new StringWriter());
- Document document = db.parse(new InputSource(new StringReader(xml)));
- Transformer transformer = TransformerFactory.newInstance()
- .newTransformer();
- transformer.setOutputProperty(OutputKeys.INDENT, "yes");
- transformer
- .setOutputProperty(XML_INDENT_AMT_PROP_NAME, XML_INDENT_SPACES);
- DOMSource source = new DOMSource(document);
- transformer.transform(source, result);
- return result.getWriter().toString();
- } catch (ParserConfigurationException | SAXException | IOException
- | TransformerFactoryConfigurationError | TransformerException e) {
- LOGGER.error("Error in formatting xml", e);
- throw new RuntimeException(e);
- }
- }
-
- private boolean isSecurityEnabled() {
- boolean securityEnabled = Boolean.valueOf(getHadoopConfigs().get(
- "security_enabled"));
- return securityEnabled;
- }
-
- private Map<String, String> getHadoopConfigs() {
- return viewContext.getInstanceData();
- }
-
-}
+ private final static Logger LOGGER = LoggerFactory
+ .getLogger(OozieProxyImpersonator.class);
+
+ private static final String OOZIEPARAM_PREFIX = "oozieparam.";
+ private static final int OOZIEPARAM_PREFIX_LENGTH = OOZIEPARAM_PREFIX
+ .length();
+ private static final String EQUAL_SYMBOL = "=";
+ private static final String OOZIE_WF_RERUN_FAILNODES_CONF_KEY = "oozie.wf.rerun.failnodes";
+ private static final String OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY = "oozie.use.system.libpath";
+
+ private ViewContext viewContext;
+
+ private static final String USER_NAME_HEADER = "user.name";
+ private static final String USER_OOZIE_SUPER = "oozie";
+ private static final String DO_AS_HEADER = "doAs";
+
+ private static final String SERVICE_URI_PROP = "oozie.service.uri";
+ private static final String DEFAULT_SERVICE_URI = "http://sandbox.hortonworks.com:11000/oozie";
+ private Utils utils=new Utils();
+ private OozieUtils oozieUtils=new OozieUtils();
+ private HDFSFileUtils hdfsFileUtils;
+ private static enum ErrorCodes {
+ OOZIE_SUBMIT_ERROR("error.oozie.submit", "Oozie Submit error"), OOZIE_IO_ERROR(
+ "error.oozie.io", "Oozie I/O error"), FILE_ACCESS_ACL_ERROR(
+ "error.file.access.control",
+ "Access Error to file due to access control"), FILE_ACCESS_UNKNOWN_ERROR(
+ "error.file.access", "Error accessing file"), WORKFLOW_PATH_EXISTS(
+ "error.workflow.path.exists", "Worfklow path exists");
+ private String errorCode;
+ private String description;
+
+ ErrorCodes(String errorCode, String description) {
+ this.errorCode = errorCode;
+ this.description = description;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+ }
+
+ @Inject
+ public OozieProxyImpersonator(ViewContext viewContext) {
+ this.viewContext = viewContext;
+ hdfsFileUtils=new HDFSFileUtils(viewContext);
+ LOGGER.info(String.format(
+ "OozieProxyImpersonator initialized for instance: %s",
+ viewContext.getInstanceName()));
+ }
+
+ @Path("/fileServices")
+ public FileServices fileServices() {
+ return new FileServices(viewContext);
+ }
+
+ @GET
+ @Path("/getCurrentUserName")
+ public Response getCurrentUserName() {
+ return Response.ok(viewContext.getUsername()).build();
+ }
+
+ @POST
+ @Path("/submitJob")
+ @Consumes({ MediaType.TEXT_PLAIN + "," + MediaType.TEXT_XML })
+ public Response submitJob(String postBody, @Context HttpHeaders headers,
+ @Context UriInfo ui, @QueryParam("app.path") String appPath,
+ @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite,
+ @QueryParam("jobType") String jobType) {
+ LOGGER.info("submit workflow job called");
+ return submitJobInternal(postBody, headers, ui, appPath, overwrite,
+ JobType.valueOf(jobType));
+ }
+
+ @POST
+ @Path("/submitWorkflow")
+ @Consumes({ MediaType.TEXT_PLAIN + "," + MediaType.TEXT_XML })
+ public Response submitWorkflow(String postBody,
+ @Context HttpHeaders headers, @Context UriInfo ui,
+ @QueryParam("app.path") String appPath,
+ @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite) {
+ LOGGER.info("submit workflow job called");
+ return submitJobInternal(postBody, headers, ui, appPath, overwrite,
+ JobType.WORKFLOW);
+ }
+
+ @POST
+ @Path("/saveWorkflow")
+ @Consumes({ MediaType.TEXT_PLAIN + "," + MediaType.TEXT_XML })
+ public Response saveWorkflow(String postBody, @Context HttpHeaders headers,
+ @Context UriInfo ui, @QueryParam("app.path") String appPath,
+ @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite) {
+ LOGGER.info("save workflow called");
+ if (StringUtils.isEmpty(appPath)) {
+ throw new RuntimeException("app path can't be empty.");
+ }
+ appPath = appPath.trim();
+ if (!overwrite) {
+ boolean fileExists = hdfsFileUtils.fileExists(appPath);
+ if (fileExists) {
+ return getFileExistsResponse();
+ }
+ }
+ postBody = utils.formatXml(postBody);
+ try {
+ String filePath = hdfsFileUtils.createWorkflowFile(getWorkflowFileName(appPath),postBody, overwrite);
+ LOGGER.info(String.format(
+ "submit workflow job done. filePath=[%s]", filePath));
+ return Response.ok().build();
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage(), ex);
+ return getRespCodeForException(ex);
+
+ }
+ }
+
+ private Response submitJobInternal(String postBody, HttpHeaders headers,
+ UriInfo ui, String appPath, Boolean overwrite, JobType jobType) {
+ if (StringUtils.isEmpty(appPath)) {
+ throw new RuntimeException("app path can't be empty.");
+ }
+ appPath = appPath.trim();
+ if (!overwrite) {
+ boolean fileExists = hdfsFileUtils.fileExists(appPath);
+ if (fileExists) {
+ return getFileExistsResponse();
+ }
+ }
+ postBody = utils.formatXml(postBody);
+ try {
+ String filePath = hdfsFileUtils.createWorkflowFile(getWorkflowFileName(appPath),postBody,overwrite);
+ LOGGER.info(String.format(
+ "submit workflow job done. filePath=[%s]", filePath));
+ } catch (Exception ex) {
+ LOGGER.error(ex.getMessage(), ex);
+ return getRespCodeForException(ex);
+
+ }
+ String response = submitWorkflowJobToOozie(headers, appPath,
+ ui.getQueryParameters(), jobType);
+ if (response != null && response.trim().startsWith("{")) {
+ // dealing with oozie giving error but with 200 response.
+ return Response.status(Response.Status.OK).entity(response).build();
+ } else {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", ErrorCodes.OOZIE_SUBMIT_ERROR.getErrorCode());
+ resp.put("message", response);
+ return Response.status(Response.Status.BAD_REQUEST).entity(resp)
+ .build();
+ }
+
+ }
+
+ private Response getRespCodeForException(Exception ex) {
+ if (ex instanceof AccessControlException) {
+ HashMap<String, String> errorDetails = getErrorDetails(
+ ErrorCodes.FILE_ACCESS_ACL_ERROR.getErrorCode(),
+ ErrorCodes.FILE_ACCESS_ACL_ERROR.getDescription(), ex);
+ return Response.status(Response.Status.BAD_REQUEST)
+ .entity(errorDetails).build();
+ }else if (ex instanceof IOException){
+ HashMap<String, String> errorDetails = getErrorDetails(
+ ErrorCodes.FILE_ACCESS_UNKNOWN_ERROR.getErrorCode(),
+ ErrorCodes.FILE_ACCESS_UNKNOWN_ERROR.getDescription(), ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+ .entity(errorDetails).build();
+ }else {
+ HashMap<String, String> errorDetails = getErrorDetails(
+ ErrorCodes.FILE_ACCESS_UNKNOWN_ERROR.getErrorCode(),
+ ErrorCodes.FILE_ACCESS_UNKNOWN_ERROR.getDescription(), ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+ .entity(errorDetails).build();
+ }
+
+
+ }
+
+ private Response getFileExistsResponse() {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", ErrorCodes.WORKFLOW_PATH_EXISTS.getErrorCode());
+ resp.put("message", ErrorCodes.WORKFLOW_PATH_EXISTS.getDescription());
+ return Response.status(Response.Status.BAD_REQUEST).entity(resp)
+ .build();
+ }
+
+ private String getWorkflowFileName(String appPath) {
+ String workflowFile = null;
+ if (appPath.endsWith(".xml")) {
+ workflowFile = appPath;
+ } else {
+ workflowFile = appPath + (appPath.endsWith("/") ? "" : "/")
+ + "workflow.xml";
+ }
+ return workflowFile;
+ }
+
+ @GET
+ @Path("/readWorkflowXml")
+ public Response readWorkflowXxml(
+ @QueryParam("workflowXmlPath") String workflowPath) {
+ if (StringUtils.isEmpty(workflowPath)) {
+ throw new RuntimeException("workflowXmlPath can't be empty.");
+ }
+ try {
+ final FSDataInputStream is = hdfsFileUtils.read(workflowPath);
+ StreamingOutput streamer = new StreamingOutput() {
+ @Override
+ public void write(OutputStream os) throws IOException,
+ WebApplicationException {
+ IOUtils.copy(is, os);
+ is.close();
+ os.close();
+ }
+ };
+ return Response.ok(streamer).status(200).build();
+ } catch(IOException e){
+ return getRespCodeForException(e);
+ }
+ }
+
+ private HashMap<String, String> getErrorDetails(String status,
+ String message, Exception ex) {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", status);
+ if (message != null) {
+ resp.put("message", message);
+ }
+ if (ex != null) {
+ resp.put("stackTrace", ExceptionUtils.getFullStackTrace(ex));
+ }
+ return resp;
+ }
+
+ @GET
+ @Path("/getDag")
+ @Produces("image/png")
+ public Response submitWorkflow(@Context HttpHeaders headers,
+ @Context UriInfo ui, @QueryParam("jobid") String jobid) {
+ String imgUrl = getServiceUri() + "/v2/job/" + jobid + "?show=graph";
+ Map<String, String> newHeaders = utils.getHeaders(headers);
+ final InputStream is = readFromOozie(headers, imgUrl, HttpMethod.GET,
+ null, newHeaders);
+ StreamingOutput streamer = new StreamingOutput() {
+
+ @Override
+ public void write(OutputStream os) throws IOException,
+ WebApplicationException {
+ IOUtils.copy(is, os);
+ is.close();
+ os.close();
+ }
+
+ };
+ return Response.ok(streamer).status(200).build();
+ }
+
+ @GET
+ @Path("/{path: .*}")
+ public Response handleGet(@Context HttpHeaders headers, @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.GET, null);
+ } catch (Exception ex) {
+ LOGGER.error("Error in GET proxy", ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+ .entity(getErrorDetailsForException("Oozie", ex)).build();
+ }
+ }
+
+ @POST
+ @Path("/{path: .*}")
+ public Response handlePost(String xml, @Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.POST, xml);
+ } catch (Exception ex) {
+ LOGGER.error("Error in POST proxy", ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+ .entity(getErrorDetailsForException("Oozie", ex)).build();
+ }
+ }
+
+ @DELETE
+ @Path("/{path: .*}")
+ public Response handleDelete(@Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.POST, null);
+ } catch (Exception ex) {
+ LOGGER.error("Error in DELETE proxy", ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+ .entity(getErrorDetailsForException("Oozie", ex)).build();
+ }
+ }
+
+ @PUT
+ @Path("/{path: .*}")
+ public Response handlePut(String body, @Context HttpHeaders headers,
+ @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.PUT, body);
+ } catch (Exception ex) {
+ LOGGER.error("Error in PUT proxy", ex);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
+ .entity(getErrorDetailsForException("Oozie", ex)).build();
+ }
+ }
+
+ private Map<String, String> getErrorDetailsForException(String component,
+ Exception ex) {
+ String errorCode = component + "exception";
+ String errorMessage = component + " Exception";
+ if (ex instanceof RuntimeException) {
+ Throwable cause = ex.getCause();
+ if (cause instanceof IOException) {
+ errorCode = component + "io.exception";
+ errorMessage = component + "IO Exception";
+ }
+ }
+ return getErrorDetails(errorCode, errorMessage, ex);
+ }
+
+ private String submitWorkflowJobToOozie(HttpHeaders headers,
+ String filePath, MultivaluedMap<String, String> queryParams,
+ JobType jobType) {
+ String nameNode = "hdfs://"
+ + viewContext.getCluster().getConfigurationValue("hdfs-site",
+ "dfs.namenode.rpc-address");
+
+ if (!queryParams.containsKey("config.nameNode")) {
+ ArrayList<String> nameNodes = new ArrayList<String>();
+ LOGGER.info("Namenode===" + nameNode);
+ nameNodes.add(nameNode);
+ queryParams.put("config.nameNode", nameNodes);
+ }
+
+ HashMap<String, String> workflowConigs = getWorkflowConfigs(filePath,
+ queryParams, jobType, nameNode);
+ String configXMl = oozieUtils.generateConfigXml(workflowConigs);
+ LOGGER.info("Config xml==" + configXMl);
+ HashMap<String, String> customHeaders = new HashMap<String, String>();
+ customHeaders.put("Content-Type", "application/xml;charset=UTF-8");
+ Response serviceResponse = consumeService(headers, getServiceUri()
+ + "/v2/jobs?" + getJobSumbitOozieParams(queryParams),
+ HttpMethod.POST, configXMl, customHeaders);
+
+ LOGGER.info("REsp from oozie status entity=="
+ + serviceResponse.getEntity());
+ if (serviceResponse.getEntity() instanceof String) {
+ return (String) serviceResponse.getEntity();
+ } else {
+ return "success";
+ }
+
+ }
+
+ private HashMap<String, String> getWorkflowConfigs(String filePath,
+ MultivaluedMap<String, String> queryParams, JobType jobType,
+ String nameNode) {
+ HashMap<String, String> workflowConigs = new HashMap<String, String>();
+ if (queryParams.containsKey("resourceManager")
+ && "useDefault".equals(queryParams.getFirst("resourceManager"))) {
+ String jobTrackerNode = viewContext.getCluster()
+ .getConfigurationValue("yarn-site",
+ "yarn.resourcemanager.address");
+ LOGGER.info("jobTrackerNode===" + jobTrackerNode);
+ workflowConigs.put("resourceManager", jobTrackerNode);
+ workflowConigs.put("jobTracker", jobTrackerNode);
+ }
+ if (queryParams != null) {
+ for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
+ if (entry.getKey().startsWith("config.")) {
+ if (entry.getValue() != null && entry.getValue().size() > 0) {
+ workflowConigs.put(entry.getKey().substring(7), entry
+ .getValue().get(0));
+ }
+ }
+ }
+ }
+
+ if (queryParams.containsKey("oozieconfig.useSystemLibPath")) {
+ String useSystemLibPath = queryParams
+ .getFirst("oozieconfig.useSystemLibPath");
+ workflowConigs.put(OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY,
+ useSystemLibPath);
+ } else {
+ workflowConigs.put(OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY, "true");
+ }
+ if (queryParams.containsKey("oozieconfig.rerunOnFailure")) {
+ String rerunFailnodes = queryParams
+ .getFirst("oozieconfig.rerunOnFailure");
+ workflowConigs.put(OOZIE_WF_RERUN_FAILNODES_CONF_KEY,
+ rerunFailnodes);
+ } else {
+ workflowConigs.put(OOZIE_WF_RERUN_FAILNODES_CONF_KEY, "true");
+ }
+ workflowConigs.put("user.name", viewContext.getUsername());
+ workflowConigs.put(oozieUtils.getJobPathPropertyKey(jobType), nameNode + filePath);
+ return workflowConigs;
+ }
+
+ private String getJobSumbitOozieParams(
+ MultivaluedMap<String, String> queryParams) {
+ StringBuilder query = new StringBuilder();
+ if (queryParams != null) {
+ for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
+ if (entry.getKey().startsWith(OOZIEPARAM_PREFIX)) {
+ if (entry.getValue() != null && entry.getValue().size() > 0) {
+ for (String val : entry.getValue()) {
+ query.append(
+ entry.getKey().substring(
+ OOZIEPARAM_PREFIX_LENGTH))
+ .append(EQUAL_SYMBOL).append(val)
+ .append("&");
+ }
+ }
+ }
+ }
+ }
+ return query.toString();
+ }
+
+ private String buildURI(UriInfo ui) {
+ String uiURI = ui.getAbsolutePath().getPath();
+ int index = uiURI.indexOf("proxy/") + 5;
+ uiURI = uiURI.substring(index);
+ String serviceURI = getServiceUri();
+ serviceURI += uiURI;
+ MultivaluedMap<String, String> params = addOrReplaceUserName(ui.getQueryParameters());
+ return serviceURI+utils.convertParamsToUrl(params);
+ }
+ private MultivaluedMap<String, String> addOrReplaceUserName(MultivaluedMap<String, String> parameters){
+ for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
+ if ("user.name".equals(entry.getKey())) {
+ ArrayList<String> vals = new ArrayList<String>(1);
+ vals.add(viewContext.getUsername());
+ entry.setValue(vals);
+ }
+ }
+ return parameters;
+ }
+
+ private String getServiceUri() {
+ String serviceURI = viewContext.getProperties().get(SERVICE_URI_PROP) != null ? viewContext
+ .getProperties().get(SERVICE_URI_PROP) : DEFAULT_SERVICE_URI;
+ return serviceURI;
+ }
+
+ private Response consumeService(HttpHeaders headers, String urlToRead,
+ String method, String body) throws Exception {
+ return consumeService(headers, urlToRead, method, body, null);
+ }
+
+ private Response consumeService(HttpHeaders headers, String urlToRead,
+ String method, String body, Map<String, String> customHeaders) {
+ Response response = null;
+ InputStream stream = readFromOozie(headers, urlToRead, method, body,
+ customHeaders);
+ String stringResponse = null;
+ try {
+ stringResponse = IOUtils.toString(stream);
+ } catch (IOException e) {
+ LOGGER.error("Error while converting stream to string", e);
+ throw new RuntimeException(e);
+ }
+ if (stringResponse.contains(Response.Status.BAD_REQUEST.name())) {
+ response = Response.status(Response.Status.BAD_REQUEST)
+ .entity(stringResponse).type(MediaType.TEXT_PLAIN).build();
+ } else {
+ response = Response.status(Response.Status.OK)
+ .entity(stringResponse).type(utils.deduceType(stringResponse))
+ .build();
+ }
+ return response;
+ }
+
+ private InputStream readFromOozie(HttpHeaders headers, String urlToRead,
+ String method, String body, Map<String, String> customHeaders) {
+
+ Map<String, String> newHeaders = utils.getHeaders(headers);
+ newHeaders.put(USER_NAME_HEADER, USER_OOZIE_SUPER);
+
+ newHeaders.put(DO_AS_HEADER, viewContext.getUsername());
+ newHeaders.put("Accept", MediaType.APPLICATION_JSON);
+ if (customHeaders != null) {
+ newHeaders.putAll(customHeaders);
+ }
+ LOGGER.info(String.format("Proxy request for url: [%s] %s", method,
+ urlToRead));
+
+ return readFromUrl(urlToRead, method, body, newHeaders);
+ }
+
+ private InputStream readFromUrl(String urlToRead, String method, String body,
+ Map<String, String> newHeaders) {
+ URLStreamProvider streamProvider = viewContext.getURLStreamProvider();
+ InputStream stream = null;
+ try {
+ if (isSecurityEnabled()) {
+ stream = streamProvider.readAsCurrent(urlToRead, method, body,
+ newHeaders);
+
+ } else {
+ stream = streamProvider.readFrom(urlToRead, method, body,
+ newHeaders);
+ }
+ } catch (IOException e) {
+ LOGGER.error("error talking to oozie", e);
+ throw new RuntimeException(e);
+ }
+ return stream;
+ }
+
+
+ private boolean isSecurityEnabled() {
+ String authType = viewContext.getCluster().getConfigurationValue(
+ "core-site", "hadoop.security.authentication");
+ LOGGER.info("Auth Type=" + authType);
+ return !"simple".equalsIgnoreCase(authType);
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieUtils.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieUtils.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieUtils.java
new file mode 100644
index 0000000..170132f
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieUtils.java
@@ -0,0 +1,71 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie.ambari.view;
+
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class OozieUtils {
+ private final static Logger LOGGER = LoggerFactory
+ .getLogger(OozieUtils.class);
+ private Utils utils = new Utils();
+
+ public String generateConfigXml(Map<String, String> map) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db;
+ try {
+ db = dbf.newDocumentBuilder();
+ Document doc = db.newDocument();
+ Element configElement = doc.createElement("configuration");
+ doc.appendChild(configElement);
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ Element propElement = doc.createElement("property");
+ configElement.appendChild(propElement);
+ Element nameElem = doc.createElement("name");
+ nameElem.setTextContent(entry.getKey());
+ Element valueElem = doc.createElement("value");
+ valueElem.setTextContent(entry.getValue());
+ propElement.appendChild(nameElem);
+ propElement.appendChild(valueElem);
+ }
+ return utils.generateXml(doc);
+ } catch (ParserConfigurationException e) {
+ LOGGER.error("error in generating config xml", e);
+ throw new RuntimeException(e);
+ }
+ }
+ public String getJobPathPropertyKey(JobType jobType) {
+ switch (jobType) {
+ case WORKFLOW:
+ return "oozie.wf.application.path";
+ case COORDINATOR:
+ return "oozie.coord.application.path";
+ case BUNDLE:
+ return "oozie.bundle.application.path";
+ }
+ throw new RuntimeException("Unknown Job Type");
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Utils.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Utils.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Utils.java
new file mode 100644
index 0000000..61d878e
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/Utils.java
@@ -0,0 +1,154 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.oozie.ambari.view;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class Utils {
+ private static final String XML_INDENT_SPACES = "4";
+ private static final String XML_INDENT_AMT_PROP_NAME = "{http://xml.apache.org/xslt}indent-amount";
+ private final static Logger LOGGER = LoggerFactory
+ .getLogger(Utils.class);
+ public String formatXml(String xml) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ try {
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ StreamResult result = new StreamResult(new StringWriter());
+ Document document = db
+ .parse(new InputSource(new StringReader(xml)));
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(XML_INDENT_AMT_PROP_NAME,
+ XML_INDENT_SPACES);
+ DOMSource source = new DOMSource(document);
+ transformer.transform(source, result);
+ return result.getWriter().toString();
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerFactoryConfigurationError | TransformerException e) {
+ LOGGER.error("Error in formatting xml", e);
+ throw new RuntimeException(e);
+ }
+ }
+ public String generateXml(Document doc){
+ DOMSource domSource = new DOMSource(doc);
+ StringWriter writer = new StringWriter();
+ StreamResult result = new StreamResult(writer);
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer;
+ try {
+ transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer.setOutputProperty(XML_INDENT_AMT_PROP_NAME,
+ XML_INDENT_SPACES);
+ try {
+ transformer.transform(domSource, result);
+ } catch (TransformerException e) {
+ throw new RuntimeException(e);
+ }
+ return writer.toString();
+ } catch (TransformerConfigurationException tce) {
+ throw new RuntimeException(tce);
+ }
+
+ }
+
+ public Map<String, String> getHeaders(HttpHeaders headers) {
+ MultivaluedMap<String, String> requestHeaders = headers
+ .getRequestHeaders();
+ Set<Entry<String, List<String>>> headerEntrySet = requestHeaders
+ .entrySet();
+ HashMap<String, String> headersMap = new HashMap<String, String>();
+ for (Entry<String, List<String>> headerEntry : headerEntrySet) {
+ String key = headerEntry.getKey();
+ List<String> values = headerEntry.getValue();
+ headersMap.put(key, strJoin(values, ","));
+ }
+ return headersMap;
+ }
+
+ public String strJoin(List<String> strings, String separator) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0, il = strings.size(); i < il; i++) {
+ if (i > 0) {
+ stringBuilder.append(separator);
+ }
+ stringBuilder.append(strings.get(i));
+ }
+ return stringBuilder.toString();
+ }
+ public MediaType deduceType(String stringResponse) {
+ if (stringResponse.startsWith("{")) {
+ return MediaType.APPLICATION_JSON_TYPE;
+ } else if (stringResponse.startsWith("<")) {
+ return MediaType.TEXT_XML_TYPE;
+ } else {
+ return MediaType.APPLICATION_JSON_TYPE;
+ }
+ }
+
+ public String convertParamsToUrl(MultivaluedMap<String, String> parameters) {
+ StringBuilder urlBuilder = new StringBuilder();
+ boolean firstEntry = true;
+ for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
+ if (firstEntry) {
+ urlBuilder.append("?");
+ } else {
+ urlBuilder.append("&");
+ }
+ boolean firstVal = true;
+ for (String val : entry.getValue()) {
+ urlBuilder.append(firstVal ? "" : "&").append(entry.getKey())
+ .append("=").append(val);
+ firstVal = false;
+ }
+ firstEntry = false;
+ }
+ return urlBuilder.toString();
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/.jshintrc
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/.jshintrc b/contrib/views/wfmanager/src/main/resources/ui/.jshintrc
new file mode 100644
index 0000000..ed9a144
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/.jshintrc
@@ -0,0 +1,38 @@
+{
+ "predef": [
+ "document",
+ "window",
+ "-Promise",
+ "vkbeautify",
+ "moment",
+ "X2JS",
+ "jsPlumb",
+ "cytoscape",
+ "dagre"
+ ],
+ "browser": true,
+ "boss": true,
+ "curly": true,
+ "debug": false,
+ "devel": true,
+ "eqeqeq": true,
+ "evil": true,
+ "forin": false,
+ "immed": false,
+ "laxbreak": false,
+ "newcap": true,
+ "noarg": true,
+ "noempty": false,
+ "nonew": false,
+ "nomen": false,
+ "onevar": false,
+ "plusplus": false,
+ "regexp": false,
+ "undef": true,
+ "sub": true,
+ "strict": false,
+ "white": false,
+ "eqnull": true,
+ "esnext": true,
+ "unused": true
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/app/components/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
index d53b459..7ea46c4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
@@ -16,9 +16,8 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations,{
+export default Ember.Component.extend({
fileBrowser : Ember.inject.service('file-browser'),
initialize : function(){
this.on('fileSelected',function(fileName){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
new file mode 100644
index 0000000..2799db5
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-config.js
@@ -0,0 +1,262 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import {Bundle} from '../domain/bundle/bundle';
+import {BundleGenerator} from '../domain/bundle/bundle-xml-generator';
+import {BundleXmlImporter} from '../domain/bundle/bundle-xml-importer';
+import { validator, buildValidations } from 'ember-cp-validations';
+import Constants from '../utils/constants';
+
+const Validations = buildValidations({
+ 'bundle.name': validator('presence', {
+ presence : true
+ }),
+ 'bundle.coordinators': {
+ validators: [
+ validator('operand-length', {
+ min : 1,
+ dependentKeys: ['bundle','bundle.coordinators.[]'],
+ message : 'Alteast one coordinator is required',
+ disabled(model, attribute) {
+ return !model.get('bundle');
+ }
+ })
+ ]
+ }
+});
+
+export default Ember.Component.extend(Ember.Evented, Validations, {
+ bundle : null,
+ propertyExtractor : Ember.inject.service('property-extractor'),
+ fileBrowser : Ember.inject.service('file-browser'),
+ workspaceManager : Ember.inject.service('workspace-manager'),
+ initialize : function(){
+ var draftBundle = this.get('workspaceManager').restoreWorkInProgress(this.get('tabInfo.id'));
+ if(draftBundle){
+ this.set('bundle', JSON.parse(draftBundle));
+ }else{
+ this.set('bundle', this.createBundle());
+ }
+ this.get('fileBrowser').on('fileBrowserOpened',function(context){
+ this.get('fileBrowser').setContext(context);
+ }.bind(this));
+ this.on('fileSelected',function(fileName){
+ this.set(this.get('filePathModel'), fileName);
+ }.bind(this));
+ if(Ember.isBlank(this.get('bundle.name'))){
+ this.set('bundle.name', Ember.copy(this.get('tabInfo.name')));
+ }
+ this.set('showErrorMessage', false);
+ this.schedulePersistWorkInProgress();
+ }.on('init'),
+ onDestroy : function(){
+ Ember.run.cancel(this.schedulePersistWorkInProgress);
+ this.persistWorkInProgress();
+ }.on('willDestroyElement'),
+ observeFilePath : Ember.observer('bundleFilePath', function(){
+ if(!this.get('bundleFilePath') || null === this.get('bundleFilePath')){
+ return;
+ }else{
+ this.sendAction('changeFilePath', this.get('tabInfo'), this.get('bundleFilePath'));
+ }
+ }),
+ nameObserver : Ember.observer('bundle.name', function(){
+ if(!this.get('bundle')){
+ return;
+ }else if(this.get('bundle') && Ember.isBlank(this.get('bundle.name'))){
+ if(!this.get('clonedTabInfo')){
+ this.set('clonedTabInfo', Ember.copy(this.get('tabInfo')));
+ }
+ this.sendAction('changeTabName', this.get('tabInfo'), this.get('clonedTabInfo.name'));
+ }else{
+ this.sendAction('changeTabName', this.get('tabInfo'), this.get('bundle.name'));
+ }
+ }),
+ schedulePersistWorkInProgress (){
+ Ember.run.later(function(){
+ this.persistWorkInProgress();
+ this.schedulePersistWorkInProgress();
+ }.bind(this), Constants.persistWorkInProgressInterval);
+ },
+ persistWorkInProgress (){
+ if(!this.get('bundle')){
+ return;
+ }
+ var json = JSON.stringify(this.get("bundle"));
+ this.get('workspaceManager').saveWorkInProgress(this.get('tabInfo.id'), json);
+ },
+ createBundle (){
+ return Bundle.create({
+ name : '',
+ kickOffTime : {
+ value : '',
+ displayValue : '',
+ type : 'date'
+ },
+ coordinators : null
+ });
+ },
+ importSampleBundle (){
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: "/sampledata/bundle.xml",
+ dataType: "text",
+ cache:false,
+ success: function(data) {
+ deferred.resolve(data);
+ }.bind(this),
+ failure : function(data){
+ deferred.reject(data);
+ }
+ });
+ return deferred;
+ },
+ importBundle (filePath){
+ this.set("bundleFilePath", filePath);
+ this.set("isImporting", false);
+ var deferred = this.getBundleFromHdfs(filePath);
+ deferred.promise.then(function(data){
+ this.getBundleFromXml(data);
+ this.set("isImporting", false);
+ }.bind(this)).catch(function(){
+ this.set("isImporting", false);
+ this.set("isImportingSuccess", false);
+ }.bind(this));
+ },
+ getBundleFromHdfs(filePath){
+ var url = Ember.ENV.API_URL + "/readWorkflowXml?workflowXmlPath="+filePath;
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: url,
+ method: 'GET',
+ dataType: "text",
+ beforeSend: function (xhr) {
+ xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ xhr.setRequestHeader("X-Requested-By", "Ambari");
+ }
+ }).done(function(data){
+ deferred.resolve(data);
+ }).fail(function(){
+ deferred.reject();
+ });
+ return deferred;
+ },
+ getBundleFromXml(bundleXml){
+ var bundleXmlImporter = BundleXmlImporter.create({});
+ var bundle = bundleXmlImporter.importBundle(bundleXml);
+ this.set("bundle", bundle);
+ },
+ actions : {
+ closeFileBrowser(){
+ this.set("showingFileBrowser", false);
+ this.get('fileBrowser').getContext().trigger('fileSelected', this.get('filePath'));
+ if(this.get('bundleFilePath')){
+ this.importBundle(Ember.copy(this.get('bundleFilePath')));
+ this.set('bundleFilePath', null);
+ }
+ },
+ openFileBrowser(model, context){
+ if(!context){
+ context = this;
+ }
+ this.get('fileBrowser').trigger('fileBrowserOpened',context);
+ this.set('filePathModel', model);
+ this.set('showingFileBrowser', true);
+ },
+ createCoordinator(){
+ this.set('coordinatorEditMode', false);
+ this.set('coordinatorCreateMode', true);
+ this.set('currentCoordinator',{
+ name : undefined,
+ appPath : undefined,
+ configuration : {
+ property : Ember.A([])
+ }
+ });
+ },
+ editCoordinator(index){
+ this.set('coordinatorEditMode', true);
+ this.set('coordinatorCreateMode', false);
+ this.set('currentCoordinatorIndex', index);
+ this.set('currentCoordinator', Ember.copy(this.get('bundle.coordinators').objectAt(index)));
+ },
+ addCoordinator(){
+ if(!this.get('bundle.coordinators')){
+ this.set('bundle.coordinators', Ember.A([]));
+ }
+ this.get('bundle.coordinators').pushObject(Ember.copy(this.get('currentCoordinator')));
+ this.set('coordinatorCreateMode', false);
+ },
+ updateCoordinator(){
+ this.get('bundle.coordinators').replace(this.get('currentCoordinatorIndex'), 1, Ember.copy(this.get('currentCoordinator')));
+ this.set('coordinatorEditMode', false);
+ },
+ deleteCoordinator(index){
+ this.get('bundle.coordinators').removeAt(index);
+ if(index === this.get('currentCoordinatorIndex')){
+ this.set('coordinatorEditMode', false);
+ }
+ },
+ cancelCoordinatorOperation(){
+ this.set('coordinatorCreateMode', false);
+ this.set('coordinatorEditMode', false);
+ },
+ confirmReset(){
+ this.set('showingResetConfirmation', true);
+ },
+ resetBundle(){
+ this.set('bundle', this.createBundle());
+ },
+ closeBundleSubmitConfig(){
+ this.set("showingJobConfig", false);
+ },
+ submitBundle(){
+ if(this.get('validations.isInvalid')) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ var bundleGenerator = BundleGenerator.create({bundle:this.get("bundle")});
+ var bundleXml = bundleGenerator.process();
+ var dynamicProperties = this.get('propertyExtractor').getDynamicProperties(bundleXml);
+ var configForSubmit = {props : dynamicProperties, xml : bundleXml, params : this.get('bundle.parameters')};
+ this.set("bundleConfigs", configForSubmit);
+ this.set("showingJobConfig", true);
+ },
+ preview(){
+ if(this.get('validations.isInvalid')) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.set("showingPreview", false);
+ var bundleGenerator = BundleGenerator.create({bundle:this.get("bundle")});
+ var bundleXml = bundleGenerator.process();
+ this.set("previewXml", vkbeautify.xml(bundleXml));
+ this.set("showingPreview", true);
+ },
+ importBundleTest(){
+ var deferred = this.importSampleBundle();
+ deferred.promise.then(function(data){
+ this.getBundleFromXml(data);
+ }.bind(this)).catch(function(e){
+ throw new Error(e);
+ });
+ },
+ openTab(type, path){
+ this.sendAction('openTab', type, path);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-coord-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-coord-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-coord-config.js
new file mode 100644
index 0000000..229b2cc
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-coord-config.js
@@ -0,0 +1,108 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'coordinator.name': validator('presence', {
+ presence : true
+ }),
+ 'coordinator.appPath': validator('presence', {
+ presence : true
+ })
+});
+export default Ember.Component.extend(Validations, {
+ initialize : function(){
+ this.on('fileSelected',function(fileName){
+ this.set(this.get('filePathModel'), fileName);
+ }.bind(this));
+ this.set('showErrorMessage', false);
+ }.on('init'),
+ isValid(){
+ if(this.get('validations.isInvalid')) {
+ this.set('showErrorMessage', true);
+ return false;
+ }
+ return true;
+ },
+ readFromHdfs(filePath){
+ var url = Ember.ENV.API_URL + "/readWorkflowXml?workflowXmlPath="+filePath;
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: url,
+ method: 'GET',
+ dataType: "text",
+ beforeSend: function (xhr) {
+ xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ xhr.setRequestHeader("X-Requested-By", "Ambari");
+ }
+ }).done(function(data){
+ deferred.resolve(data);
+ }).fail(function(){
+ deferred.reject();
+ });
+ return deferred;
+ },
+ importSampleCoordinator (){
+ var deferred = Ember.RSVP.defer();
+ Ember.$.ajax({
+ url: "/sampledata/coordinator.xml",
+ dataType: "text",
+ cache:false,
+ success: function(data) {
+ deferred.resolve(data);
+ }.bind(this),
+ failure : function(data){
+ deferred.reject(data);
+ }
+ });
+ return deferred;
+ },
+ actions : {
+ openFileBrowser(model){
+ this.set('filePathModel', model);
+ this.sendAction("openFileBrowser", model, this);
+ },
+ addCoordinator(){
+ if(this.isValid()){
+ this.sendAction('add');
+ }
+ },
+ updateCoordinator(){
+ if(this.isValid()){
+ this.sendAction('update');
+ }
+ },
+ cancelCoordinatorOperation(){
+ this.sendAction('cancel');
+ },
+ openTab(type, path){
+ this.sendAction('openTab', type, path);
+ },
+ showCoordinatorName(){
+ this.set('coordinatorName', null);
+ var deferred = this.readFromHdfs(this.get('coordinator.appPath'));
+ deferred.promise.then(function(data){
+ var x2js = new X2JS();
+ var coordJson = x2js.xml_str2json(data);
+ this.set('coordinatorName', coordJson["coordinator-app"]._name);
+ }.bind(this)).catch(function(){
+ this.set('coordinatorName', null);
+ }.bind(this));
+ }
+ }
+});
[07/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/map-reduce-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/map-reduce-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/map-reduce-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/map-reduce-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
index 45dea7a..ae453a0 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-config.js
@@ -33,9 +33,12 @@ export default Ember.Component.extend({
}
}.on('willDestroyElement'),
addProperty (){
+ alert(this.get("validations"));
this.get('configuration.property').pushObject({name:this.get('propertyName'),value:this.get('propertyValue')});
- this.set('propertyName', "");
- this.set('propertyValue', "");
+ //if(this.get("doNotInitialize")){
+ this.set('propertyName', "");
+ this.set('propertyValue', "");
+ //}
},
actions : {
addProperty () {
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-info.js
new file mode 100644
index 0000000..7a7c38d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/name-value-info.js
@@ -0,0 +1,21 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/named-properties.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/named-properties.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/named-properties.js
index 067d643..f235018 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/named-properties.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/named-properties.js
@@ -15,18 +15,25 @@
* limitations under the License.
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'property.value': validator('presence', {
+ presence : true,
+ disabled(model){
+ return !model.get('required');
+ },
+ message : 'Required'
+ })
+});
+
+export default Ember.Component.extend(Validations, {
initialize : function () {
this.sendAction('register', this, this);
}.on('init'),
- validations : {
- 'property.value': {
- presence: {
- 'if' :'required',
- 'message' : 'Required'
- }
+ onDestroy : function () {
+ if(this.get('unregisterRequired')){
+ this.sendAction('unregister', this, this);
}
- }
+ }.on('willDestroyElement')
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action.js
index ee24871..be983a9 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/pig-action.js
@@ -16,9 +16,14 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel.script': validator('presence', {
+ presence : true
+ })
+});
+export default Ember.Component.extend(Validations,{
setUp : function(){
if(this.get('actionModel.jobXml') === undefined){
this.set("actionModel.jobXml", Ember.A([]));
@@ -54,13 +59,6 @@ export default Ember.Component.extend(EmberValidations,{
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.script': {
- presence: {
- 'message' : 'You need to provide a value for Script',
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-fs.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-fs.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-fs.js
index 9437c25..3c425d9 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-fs.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-fs.js
@@ -15,9 +15,8 @@
* limitations under the License.
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations, {
+export default Ember.Component.extend({
mkdirORdeleteORtouchz: true,
mkdir: 1,
delete: 0,
@@ -96,8 +95,8 @@ export default Ember.Component.extend(EmberValidations, {
var gPerm = this.formPermissions(this.get("gread"), this.get("gwrite"), this.get("gexecute"), "g");
var rPerm = this.formPermissions(this.get("rread"), this.get("rwrite"), this.get("rexecute"), "r");
var permissionsObj = {};
- permissionsObj = $.extend(true, oPerm, gPerm);
- permissionsObj = $.extend(true, permissionsObj, rPerm);
+ permissionsObj = Ember.$.extend(true, oPerm, gPerm);
+ permissionsObj = Ember.$.extend(true, permissionsObj, rPerm);
var perm = oPerm.operm + ""+ gPerm.gperm + ""+ rPerm.rperm;
this.get('fsOps').pushObject({
settings: {
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-info.js
new file mode 100644
index 0000000..7a7c38d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config-info.js
@@ -0,0 +1,21 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config.js
index 038428f..6bb2ee4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/prepare-config.js
@@ -16,9 +16,8 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations,{
+export default Ember.Component.extend({
multivalued: true,
prepareType : 'mkdir',
fileBrowser : Ember.inject.service('file-browser'),
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
new file mode 100644
index 0000000..31f9df8
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/preview-dialog.js
@@ -0,0 +1,20 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/property-value-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/property-value-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/property-value-config.js
new file mode 100644
index 0000000..7a7c38d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/property-value-config.js
@@ -0,0 +1,21 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
new file mode 100644
index 0000000..b41f743
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/save-wf.js
@@ -0,0 +1,170 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+import Constants from '../utils/constants';
+import { validator, buildValidations } from 'ember-cp-validations';
+
+const Validations = buildValidations({
+ 'filePath': validator('presence', {
+ presence : true
+ })
+});
+
+
+export default Ember.Component.extend(Validations, {
+ showingFileBrowser : false,
+ jobXml : "",
+ overwritePath : false,
+ savingInProgress : false,
+ isStackTraceVisible: false,
+ isStackTraceAvailable: false,
+ alertType : "",
+ alertMessage : "",
+ alertDetails : "",
+ filePath : "",
+ showErrorMessage: false,
+ displayName : Ember.computed('type', function(){
+ if(this.get('type') === 'wf'){
+ return "Workflow";
+ }else if(this.get('type') === 'coord'){
+ return "Coordinator";
+ }else{
+ return "Bundle";
+ }
+ }),
+ initialize :function(){
+ this.set("jobXml", this.get("jobConfigs").xml);
+ this.set('filePath', Ember.copy(this.get('jobFilePath')));
+ }.on('init'),
+ rendered : function(){
+ this.$("#configureJob").on('hidden.bs.modal', function () {
+ this.sendAction('closeJobConfigs');
+ }.bind(this));
+ this.$("#configureJob").modal("show");
+ }.on('didInsertElement'),
+ showNotification(data){
+ if (!data){
+ return;
+ }
+ if (data.type === "success"){
+ this.set("alertType", "success");
+ }
+ if (data.type === "error"){
+ this.set("alertType", "danger");
+ }
+ this.set("alertDetails", data.details);
+ this.set("alertMessage", data.message);
+ if(data.stackTrace.length){
+ this.set("stackTrace", data.stackTrace);
+ this.set("isStackTraceAvailable", true);
+ } else {
+ this.set("isStackTraceAvailable", false);
+ }
+ },
+ saveJob(){
+ var url = Ember.ENV.API_URL + "/saveWorkflow?app.path=" + this.get("filePath") + "&overwrite=" + this.get("overwritePath");
+ Ember.$.ajax({
+ url: url,
+ method: "POST",
+ dataType: "text",
+ contentType: "text/plain;charset=utf-8",
+ beforeSend: function(request) {
+ request.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ request.setRequestHeader("X-Requested-By", "workflow-designer");
+ },
+ data: this.get("jobXml"),
+ success: function(response) {
+ //var result=JSON.parse(response);
+ this.showNotification({
+ "type": "success",
+ "message": "Workflow have been saved"
+ });
+ this.set("savingInProgress",false);
+ }.bind(this),
+ error: function(response) {
+ console.log(response);
+ this.set("savingInProgress",false);
+ this.set("isStackTraceVisible",true);
+ this.showNotification({
+ "type": "error",
+ "message": "Error occurred while saving "+ this.get('displayName').toLowerCase(),
+ "details": this.getParsedErrorResponse(response),
+ "stackTrace": this.getStackTrace(response.responseText)
+ });
+ }.bind(this)
+ });
+ },
+ getStackTrace(data){
+ if(data){
+ try{
+ var stackTraceMsg = JSON.parse(data).stackTrace;
+ if(!stackTraceMsg){
+ return "";
+ }
+ if(stackTraceMsg instanceof Array){
+ return stackTraceMsg.join("").replace(/\tat /g, '<br/> at ');
+ } else {
+ return stackTraceMsg.replace(/\tat /g, '<br/> at ');
+ }
+ } catch(err){
+ return "";
+ }
+ }
+ return "";
+ },
+ getParsedErrorResponse (response){
+ var detail;
+ if (response.responseText && response.responseText.charAt(0)==="{"){
+ var jsonResp=JSON.parse(response.responseText);
+ if (jsonResp.status==="workflow.oozie.error"){
+ detail="Oozie error. Please check the workflow.";
+ }else if(jsonResp.message && jsonResp.message.indexOf("<html>") > -1){
+ detail= "";
+ }else{
+ detail=jsonResp.message;
+ }
+ }else{
+ detail=response;
+ }
+ return detail;
+ },
+ actions: {
+ selectFile(){
+ this.set("showingFileBrowser",true);
+ },
+ showStackTrace(){
+ this.set("isStackTraceVisible", true);
+ },
+ hideStackTrace(){
+ this.set("isStackTraceVisible", false);
+ },
+ closeFileBrowser(){
+ this.set("showingFileBrowser",false);
+ },
+ saveWorkflow(){
+ if(!this.get("validations.isInvalid")){
+ this.sendAction("setFilePath", this.get("filePath"));
+ this.set('showErrorMessage', true);
+ this.saveJob();
+ }
+ },
+ closePreview(){
+ this.set("showingPreview",false);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action.js
index a1445dc..e4e33dd 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/shell-action.js
@@ -16,9 +16,18 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel.exec': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.jobTracker': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations,{
initialize : function(){
this.sendAction('register','shellAction', this);
this.on('fileSelected',function(fileName){
@@ -47,13 +56,6 @@ export default Ember.Component.extend(EmberValidations,{
this.set("actionModel.configuration.property", Ember.A([]));
}
}.on('didInsertElement'),
- validations : {
- 'actionModel.exec': {
- presence: {
- 'message' : 'You need to provide a value for Exec'
- }
- }
- },
observeError :function(){
if(this.$('#collapseOne label.text-danger').length > 0 && !this.$('#collapseOne').hasClass("in")){
this.$('#collapseOne').collapse('show');
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/sla-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/sla-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/sla-info.js
index a1bad85..7390205 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/sla-info.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/sla-info.js
@@ -15,12 +15,92 @@
* limitations under the License.
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
+import { v1, v4 } from "ember-uuid";
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'nominalTime': {
+ validators: [
+ validator('presence', {
+ presence : true,
+ disabled(model, attribute) {
+ return !model.get('slaEnabled');
+ },
+ dependentKeys : ['slaEnabled']
+ }),
+ validator('date', {
+ disabled(model, attribute) {
+ return !model.get('slaEnabled');
+ },
+ format: 'MM/DD/YYYY hh:mm A',
+ dependentKeys : ['slaEnabled']
+ }),
+ ]
+ },
+ 'slaInfo.shouldEnd.time': {
+ validators: [
+ validator('presence', {
+ presence : true,
+ disabled(model, attribute) {
+ return !model.get('slaEnabled');
+ },
+ dependentKeys : ['slaEnabled']
+ }),
+ validator('number', {
+ disabled(model) {
+ return !model.get('slaEnabled');
+ },
+ allowString : true,
+ allowBlank : true,
+ integer : true,
+ dependentKeys : ['slaEnabled']
+ }),
+ ]
+ },
+ 'slaInfo.shouldStart.time': validator('number', {
+ disabled(model) {
+ return !model.get('slaEnabled');
+ },
+ allowString : true,
+ allowBlank : true,
+ integer : true,
+ dependentKeys : ['slaEnabled']
+ }),
+ 'slaInfo.maxDuration.time': validator('number', {
+ disabled(model) {
+ return !model.get('slaEnabled');
+ },
+ allowString : true,
+ allowBlank : true,
+ integer : true,
+ dependentKeys : ['slaEnabled']
+ }),
+ 'slaInfo.shouldStart.unit':validator('presence', {
+ presence : true,
+ disabled(model) {
+ return !model.get('slaEnabled') || !model.get('slaInfo.shouldStart.time');
+ },
+ dependentKeys : ['slaEnabled', 'slaInfo.shouldStart.time']
+ }),
+ 'slaInfo.shouldEnd.unit':validator('presence', {
+ presence : true,
+ disabled(model) {
+ return !model.get('slaEnabled') || !model.get('slaInfo.shouldEnd.time');
+ },
+ dependentKeys : ['slaEnabled', 'slaInfo.shouldEnd.time']
+ }),
+ 'slaInfo.maxDuration.unit':validator('presence', {
+ presence : true,
+ disabled(model) {
+ return !model.get('slaEnabled') || !model.get('slaInfo.maxDuration.time');
+ },
+ dependentKeys : ['slaEnabled', 'slaInfo.maxDuration.time']
+ })
+});
+
+export default Ember.Component.extend(Validations, {
alertEvents: Ember.A([]),
timeUnitOptions : Ember.A([]),
- nominalTime : '',
initialize : function(){
this.set('alertEvents', Ember.A([]));
this.get('alertEvents').pushObject({eventType:'start_miss', alertEnabled:false, displayName :'Start Miss'});
@@ -53,6 +133,7 @@ export default Ember.Component.extend(EmberValidations, {
}
}
Ember.addObserver(this, 'nominalTime', this, this.nominalTimeObserver);
+ this.set('collapseId', v1());
}.on('init'),
alertEventsObserver : function(){
var alerts = this.get('alertEvents').filterBy('alertEnabled',true).mapBy('eventType');
@@ -64,7 +145,7 @@ export default Ember.Component.extend(EmberValidations, {
Ember.removeObserver(this, 'nominalTime', this, this.nominalTimeObserver);
}.on('willDestroyElement'),
elementsInserted : function() {
- this.$('#nominalTime').datetimepicker({
+ this.$('input[name="nominalTime"]').datetimepicker({
useCurrent: false,
showClose : true,
defaultDate : this.get('slaInfo.nominalTime')
@@ -78,65 +159,6 @@ export default Ember.Component.extend(EmberValidations, {
var date = new Date(this.get('nominalTime'));
this.set('slaInfo.nominalTime',moment(date).format("YYYY-MM-DDTHH:mm")+'Z');
},
- shouldEnd : Ember.computed.alias('slaInfo.shouldEnd'),
- shouldStart : Ember.computed.alias('slaInfo.shouldStart'),
- maxDuration : Ember.computed.alias('slaInfo.maxDuration'),
- validations : {
- 'nominalTime': {
- presence: {
- 'if': 'slaEnabled',
- 'message' : 'Required',
- }
- },
- 'shouldEnd.time': {
- presence: {
- 'if': 'slaEnabled',
- 'message' : 'Required',
- },
- numericality: {
- 'if': 'slaEnabled',
- onlyInteger: true,
- greaterThan: 0,
- 'message' : 'Number Only'
- }
- },
- 'shouldStart.time': {
- numericality: {
- 'if': 'slaEnabled',
- allowBlank :true,
- onlyInteger: true,
- greaterThan: 0,
- message : 'Number Only'
- }
- },
- 'maxDuration.time': {
- numericality: {
- 'if': 'slaEnabled',
- allowBlank :true,
- onlyInteger: true,
- greaterThan: 0,
- message : 'Number Only'
- }
- },
- 'shouldStart.unit': {
- presence: {
- 'if': 'shouldStart.time',
- 'message' : 'Required',
- }
- },
- 'shouldEnd.unit': {
- presence: {
- 'if': 'slaEnabled',
- 'message' : 'Required',
- }
- },
- 'maxDuration.unit': {
- presence: {
- 'if': 'maxDuration.time',
- 'message' : 'Required',
- }
- }
- },
slaObserver : function(){
if(this.get('slaEnabled')){
this.$('#slaCollapse').collapse('show');
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action.js
index 4cb74d8..1a778c4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/spark-action.js
@@ -16,10 +16,20 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
import Constants from '../utils/constants';
-
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel.master': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.jar': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.sparkName': validator('presence', {
+ presence : true
+ })
+});
+export default Ember.Component.extend(Validations,{
setup : function(){
if(this.get('actionModel.jobXml') === undefined){
this.set("actionModel.jobXml", Ember.A([]));
@@ -41,6 +51,7 @@ export default Ember.Component.extend(EmberValidations,{
this.set("actionModel.configuration.property", Ember.A([]));
}
this.set('mastersList',Ember.copy(Constants.sparkMasterList));
+ this.set('isJar', this.get('actionModel.jar') && this.get('actionModel.jar').endsWith('.jar'));
this.sendAction('register','sparkAction', this);
}.on('init'),
initialize : function(){
@@ -68,27 +79,27 @@ export default Ember.Component.extend(EmberValidations,{
this.set('actionModel.class', undefined);
}
}),
- validations : {
- 'actionModel.master': {
- presence: {
- 'message' : 'You need to provide a value for Runs on (Master)'
- }
- },
- 'actionModel.jar': {
- presence: {
- 'message' : 'You need to provide a value for Application'
- },
- format : {
- 'with' : /\.jar$|\.py$/i,
- 'message' : 'You need to provide a .jar or .py file'
- }
- },
- 'actionModel.sparkName': {
- presence: {
- 'message' : 'You need to provide a value for Name'
- }
- }
- },
+ // validations : {
+ // 'actionModel.master': {
+ // presence: {
+ // 'message' : 'You need to provide a value for Runs on (Master)'
+ // }
+ // },
+ // 'actionModel.jar': {
+ // presence: {
+ // 'message' : 'You need to provide a value for Application'
+ // },
+ // format : {
+ // 'with' : /\.jar$|\.py$/i,
+ // 'message' : 'You need to provide a .jar or .py file'
+ // }
+ // },
+ // 'actionModel.sparkName': {
+ // presence: {
+ // 'message' : 'You need to provide a value for Name'
+ // }
+ // }
+ // },
observeError :function(){
if(this.$('#collapseOne label.text-danger').length > 0 && !this.$('#collapseOne').hasClass("in")){
this.$('#collapseOne').collapse('show');
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action.js
index 847cccd..13eb6e5 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/sqoop-action.js
@@ -16,9 +16,8 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
-export default Ember.Component.extend(EmberValidations,{
+export default Ember.Component.extend({
sqoopSendType : Ember.observer('isArg',function(){
if(this.get('isArg')){
this.set("actionModel.command", undefined);
@@ -61,8 +60,6 @@ export default Ember.Component.extend(EmberValidations,{
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action.js
index 3ae1f12..d879a0c 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/ssh-action.js
@@ -16,9 +16,17 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'actionModel.host': validator('presence', {
+ presence : true
+ }),
+ 'actionModel.command': validator('presence', {
+ presence : true
+ })
+});
+export default Ember.Component.extend(Validations, {
fileBrowser : Ember.inject.service('file-browser'),
javaOptsObserver : Ember.observer('isSingle',function(){
if(this.get('isSingle')){
@@ -54,18 +62,6 @@ export default Ember.Component.extend(EmberValidations, {
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.host': {
- presence: {
- 'message' : 'You need to provide a value for host',
- }
- },
- 'actionModel.command': {
- presence: {
- 'message' : 'You need to provide a value for command',
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow-action-info.js
new file mode 100644
index 0000000..3192c72
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow-action-info.js
@@ -0,0 +1,25 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Component.extend({
+ actions : {
+ hideNotification(){
+ this.sendAction("hideNotification");
+ }
+ }
+});
+
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow.js
index 50ac5bd..06cec22 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/sub-workflow.js
@@ -16,9 +16,15 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations,{
+const Validations = buildValidations({
+ 'actionModel.appPath': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(Validations,{
setUp : function(){
if(this.get('actionModel.configuration') === undefined){
this.set("actionModel.configuration",{});
@@ -36,13 +42,6 @@ export default Ember.Component.extend(EmberValidations,{
this.$('#collapseOne').collapse('show');
}
}.on('didUpdate'),
- validations : {
- 'actionModel.appPath': {
- presence: {
- 'message' : 'You need to provide a value for app path'
- }
- }
- },
actions : {
openFileBrowser(model, context){
if(undefined === context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/transition-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/transition-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/transition-config.js
index ccf69de..ca45b1f 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/transition-config.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/transition-config.js
@@ -16,32 +16,31 @@
*/
import Ember from 'ember';
-import EmberValidations,{ validator } from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
import {FindNodeMixin} from '../domain/findnode-mixin';
-export default Ember.Component.extend(FindNodeMixin, EmberValidations, {
+const Validations = buildValidations({
+ 'transition.errorNode.name': validator('presence', {
+ presence : true
+ })
+});
+
+export default Ember.Component.extend(FindNodeMixin, Validations, {
selectedKillNode : '',
initialize : function(){
this.set('descendantNodes',this.getDesendantNodes(this.get('currentNode')));
- this.set('okToNode', this.getOKToNode(this.get('currentNode')));
+ if(!this.get('transition.okToNode')){
+ var defaultOkToNode = this.getOKToNode(this.get('currentNode'));
+ this.set('transition.okToNode', defaultOkToNode);
+ this.set('defaultOkToNode', defaultOkToNode);
+ }
this.sendAction('register','transition', this);
if(Ember.isBlank(this.get('transition.errorNode.name'))){
this.set('transition.errorNode', this.get('killNodes').objectAt(0));
}
}.on('init'),
- //Work-around : Issue in ember-validations framework
- errorNode : Ember.computed.alias('transition.errorNode'),
- validations : {
- 'errorNode.name': {
- inline : validator(function() {
- if(!this.get('transition.errorNode.name') || this.get('transition.errorNode.name') === ""){
- return "You need to provide an error-to transition";
- }
- })
- }
- },
actions : {
- onSelectChange (value){
+ errorToHandler (value){
this.set('selectedKillNode', value);
if(this.get('selectedKillNode') === 'createNew'){
this.set('transition.errorNode.name', "");
@@ -60,8 +59,19 @@ export default Ember.Component.extend(FindNodeMixin, EmberValidations, {
}
}
},
- okNodeHandler (value){
-
+ okToHandler (name){
+ var validOkToNodes = this.get('currentNode.validOkToNodes');
+ var node = validOkToNodes.findBy('name',name);
+ if(node.id !== this.get('defaultOkToNode').id){
+ this.set('showWarning', true);
+ }else{
+ this.set('showWarning', false);
+ }
+ this.set('transition.okToNode', node);
+ },
+ undoChangeOkTo(){
+ this.set('transition.okToNode', this.get('defaultOkToNode'));
+ this.set('showWarning', false);
}
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
index 502fe50..8ee5a0a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-action-editor.js
@@ -16,11 +16,10 @@
*/
import Ember from 'ember';
-import EmberValidations from 'ember-validations';
import Constants from '../utils/constants';
import {SlaInfo} from '../domain/sla-info';
-export default Ember.Component.extend(EmberValidations, Ember.Evented,{
+export default Ember.Component.extend( Ember.Evented,{
actionIcons : {
"hive": "server",
"hive2": "server",
@@ -111,30 +110,14 @@ export default Ember.Component.extend(EmberValidations, Ember.Evented,{
}
}.on('didUpdate'),
validateChildrenComponents(){
- var validationPromises = [];
- var deferred = Ember.RSVP.defer();
- if(this.get('childComponents').size === 0){
- deferred.resolve(true);
- }else{
- this.get('childComponents').forEach((childComponent)=>{
- if(!childComponent.validations){
- return;
- }
- var validationDeferred = Ember.RSVP.defer();
- childComponent.validate().then(()=>{
- validationDeferred.resolve();
- }).catch((e)=>{
- validationDeferred.reject(e);
- });
- validationPromises.push(validationDeferred.promise);
- });
- Ember.RSVP.Promise.all(validationPromises).then(function(){
- deferred.resolve(true);
- }).catch(function(e){
- deferred.reject(e);
- });
- }
- return deferred;
+ var isChildComponentsValid = true;
+ this.get('childComponents').forEach((context)=>{
+ if(context.get('validations') && context.get('validations.isInvalid')){
+ isChildComponentsValid = false;
+ context.set('showErrorMessage', true);
+ }
+ }.bind(this));
+ return isChildComponentsValid;
},
processMultivaluedComponents(){
this.get('childComponents').forEach((childComponent)=>{
@@ -157,19 +140,16 @@ export default Ember.Component.extend(EmberValidations, Ember.Evented,{
this.sendAction('close');
},
save () {
- var isFormValid = this.validateChildrenComponents();
- isFormValid.promise.then(function(){
- this.validate().then(function(){
- this.processMultivaluedComponents();
- this.processStaticProps();
- this.$('#action_properties_dialog').modal('hide');
- this.sendAction('addKillNode', this.get('transition.errorNode'));
- this.set('saveClicked', true);
- }.bind(this)).catch(function(e){
- }.bind(this));
- }.bind(this)).catch(function (e) {
- });
-
+ var isChildComponentsValid = this.validateChildrenComponents();
+ if(this.get('validations.isInvalid') || !isChildComponentsValid) {
+ this.set('showErrorMessage', true);
+ return;
+ }
+ this.processMultivaluedComponents();
+ this.processStaticProps();
+ this.$('#action_properties_dialog').modal('hide');
+ this.sendAction('setNodeTransitions', this.get('transition'));
+ this.set('saveClicked', true);
},
openFileBrowser(model, context){
if(!context){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
index 95a7f08..7fc1c94 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-actions.js
@@ -17,12 +17,19 @@
import Ember from 'ember';
export default Ember.Component.extend({
+ clipboardHasContents : Ember.computed.oneWay('clipboard', function(){
+ return !Ember.isEmpty(this.get('clipboard'));
+ }),
actions : {
addAction : function(type){
this.$(".dr_action").css("background-color", "#fff");
this.$("[data-type="+type+"]").css("background-color", "#538EC0");
this.$(this.get('element')).popover('hide');
this.sendAction("addNode", type);
+ },
+ pasteNode(){
+ this.$(this.get('element')).popover('hide');
+ this.sendAction("pasteNode");
}
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-credentials.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-credentials.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-credentials.js
index ae24770..1072ca4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-credentials.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-credentials.js
@@ -42,51 +42,44 @@ export default Ember.Component.extend(Ember.Evented, {
}
});
},
- validateChildrenComponents(){
- var validationPromises = [];
- var deferred = Ember.RSVP.defer();
- if(this.get('childComponents').size === 0){
- deferred.resolve(true);
- }else{
- this.get('childComponents').forEach((childComponent)=>{
- if(!childComponent.validations){
- return;
- }
- var validationDeferred = Ember.RSVP.defer();
- childComponent.validate().then(()=>{
- validationDeferred.resolve();
- }).catch((e)=>{
- validationDeferred.reject(e);
- });
- validationPromises.push(validationDeferred.promise);
- });
- Ember.RSVP.Promise.all(validationPromises).then(function(){
- deferred.resolve(true);
- }).catch(function(e){
- deferred.reject(e);
- });
- }
- return deferred;
- },
actions : {
register(component, context){
this.get('childComponents').set(component, context);
},
+ createCredentials(){
+ this.set('editMode', false);
+ this.set('createMode',true);
+ },
+ editCredentials(index){
+ this.set('createMode', false);
+ this.set('editMode',true);
+ this.set('currentCredentialIndex', index);
+ this.set('currentCredentials', Ember.copy(this.get('credentialsList').objectAt(index)));
+ },
+ updateCredentials(){
+ this.set('editMode', false);
+ this.get('credentialsList').replace(this.get('currentCredentialIndex'), 1, Ember.copy(this.get('currentCredentials')));
+ },
addCredentials (credentialsInfo){
this.get('credentialsList').pushObject(credentialsInfo);
+ this.set('createMode', false);
+ },
+ deleteCredentials(index){
+ this.get('credentialsList').removeAt(index);
+ if(index === this.get('currentCredentialIndex')){
+ this.set('editMode', false);
+ }
+ },
+ cancelCreateMode(){
+ this.set('createMode', false);
},
- deleteCredentials(name){
- var credentials = this.get('credentialsList').findBy('name', name);
- this.get('credentialsList').removeObject(credentials);
+ cancelEditMode(){
+ this.set('editMode', false);
},
saveCredentials (){
- var isFormValid = this.validateChildrenComponents();
- isFormValid.promise.then(function(){
- this.processMultivaluedComponents();
- this.set('workflowCredentials', Ember.copy(this.get('credentialsList')));
- this.$('#workflow_credentials_dialog').modal('hide');
- }.bind(this)).catch(function (e) {
- });
+ this.processMultivaluedComponents();
+ this.set('workflowCredentials', Ember.copy(this.get('credentialsList')));
+ this.$('#workflow_credentials_dialog').modal('hide');
}
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-job-action-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-job-action-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-job-action-info.js
new file mode 100644
index 0000000..9a2c9cc
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-job-action-info.js
@@ -0,0 +1,22 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ actions : {
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-node.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-node.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-node.js
index e51135e..0718152 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-node.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-node.js
@@ -72,6 +72,12 @@ export default Ember.Component.extend(Ember.Evented,{
registerAddBranchAction(component){
this.set("addBranchListener",component);
},
+ showNotification(node){
+ this.sendAction("showNotification", node);
+ },
+ // hideNotification(){
+ // this.sendAction("hideNotification");
+ // },
openEditor (){
this.sendAction("openEditor", this.get('node'));
},
@@ -86,6 +92,9 @@ export default Ember.Component.extend(Ember.Evented,{
},
addDecisionBranch(settings){
this.sendAction("addDecisionBranch",settings);
+ },
+ copyNode(){
+ this.sendAction("copyNode", this.get('node'));
}
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-parameters.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-parameters.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-parameters.js
index 1f75e64..f3a25ac 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-parameters.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-parameters.js
@@ -15,9 +15,19 @@
* limitations under the License.
*/
import Ember from 'ember';
-import EmberValidations,{ validator } from 'ember-validations';
+import { validator, buildValidations } from 'ember-cp-validations';
-export default Ember.Component.extend(EmberValidations, {
+const Validations = buildValidations({
+ 'parameters.configuration.property': {
+ validators: [
+ validator('unique-name', {
+ dependentKeys: ['parameters.configuration.property.[]']
+ })
+ ]
+ }
+});
+export default Ember.Component.extend(Validations, {
+ saveClicked : false,
initialize : function(){
if(this.get('parameters') === undefined || this.get('parameters') === null){
this.set('parameters',{});
@@ -29,27 +39,15 @@ export default Ember.Component.extend(EmberValidations, {
this.sendAction('register','workflowParameters',this);
}.on('init'),
- validations : {
- 'parameters': {
- inline : validator(function() {
- var nameMap = [], errorMsg = undefined;
- if(this.get('parameters.configuration.property')){
- this.get('parameters.configuration.property').forEach(function(item, index){
- if(!item.name){
- errorMsg = "Name cannot be blank";
- } else if(nameMap.indexOf(item.name) > -1){
- errorMsg = "Name cannot be duplicate";
- } else{
- nameMap.push(item.name);
- }
- });
- if(errorMsg){
- return errorMsg;
- }
- }
- })
+ displayName : Ember.computed('type', function(){
+ if(this.get('type') === 'wf'){
+ return "Workflow";
+ }else if(this.get('type') === 'coord'){
+ return "Coordinator";
+ }else{
+ return "Bundle";
}
- },
+ }),
rendered : function(){
this.$('#workflow_parameters_dialog').modal({
backdrop: 'static',
@@ -57,24 +55,28 @@ export default Ember.Component.extend(EmberValidations, {
});
this.$('#workflow_parameters_dialog').modal('show');
this.$('#workflow_parameters_dialog').modal().on('hidden.bs.modal', function() {
- if(this.get('saveClicked')){
- this.sendAction('saveWorkFlowParam');
- }else{
- this.sendAction('closeWorkFlowParam');
- }
+ if(this.get('saveClicked')){
+ this.sendAction('saveWorkFlowParam');
+ }else{
+ this.sendAction('closeWorkFlowParam');
+ }
}.bind(this));
}.on('didInsertElement'),
actions : {
register(component, context){
this.set('nameValueContext', context);
},
+ close (){
+ this.$('#workflow_parameters_dialog').modal('hide');
+ this.set('saveClicked', false);
+ },
saveParameters (){
- this.get("nameValueContext").trigger("bindInputPlaceholder");
- this.validate().then(function(){
+ if(!this.get('validations.isInvalid')){
+ this.get("nameValueContext").trigger("bindInputPlaceholder");
this.set('saveClicked', true);
this.$('#workflow_parameters_dialog').modal('hide');
- }.bind(this)).catch(function(e){
- }.bind(this));
+ return ;
+ }
}
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-sla.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-sla.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-sla.js
index dac325f..6d504c6 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-sla.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/workflow-sla.js
@@ -15,10 +15,9 @@
* limitations under the License.
*/
import Ember from 'ember';
-import {SlaInfo} from '../domain/sla-info'
-import EmberValidations from 'ember-validations';
+import {SlaInfo} from '../domain/sla-info';
-export default Ember.Component.extend(EmberValidations,{
+export default Ember.Component.extend({
slaInfo : {},
initialize : function(){
this.set('slaInfo',Ember.copy(this.get('workflowSla')));
@@ -35,13 +34,13 @@ export default Ember.Component.extend(EmberValidations,{
}.on('didInsertElement'),
actions : {
saveWorkflowSla () {
- this.get('slaContext').validate().then(()=>{
+ if(this.get('slaContext').get('validations.isInvalid')){
+ this.get('slaContext').set('showErrorMessage', true);
+ return;
+ }else{
this.set('workflowSla', this.get('slaInfo'));
this.$('#workflow_sla_dialog').modal('hide');
- }.bind(this)). catch(()=>{
-
- });
-
+ }
},
register (name, context) {
this.set('slaContext', context);
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/controllers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design.js b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design.js
index 285ad19..689ec0d 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/controllers/design.js
@@ -18,9 +18,4 @@
import Ember from 'ember';
export default Ember.Controller.extend({
- queryParams: "appPath",
- appPath : null,
- model: function(params) {
- return {};
- }
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
new file mode 100644
index 0000000..c25b953
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/action-type-resolver.js
@@ -0,0 +1,62 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+import * as actionJobHandler from '../domain/actionjob_hanlder';
+
+var ActionTypeResolver=Ember.Object.extend({
+ actionJobHandlerMap:null,
+ validStandardActionProps:["ok","error","info"],
+ init(){
+ var settings={schemaVersions:this.schemaVersions};
+ this.actionJobHandlerMap=new Map();
+ this.actionJobHandlerMap.set("java",actionJobHandler.JavaActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("pig",actionJobHandler.PigActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("hive",actionJobHandler.HiveActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("hive2",actionJobHandler.Hive2ActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("sqoop",actionJobHandler.SqoopActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("shell",actionJobHandler.ShellActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("spark",actionJobHandler.SparkActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("map-reduce",actionJobHandler.MapRedActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("sub-workflow",actionJobHandler.SubWFActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("distcp",actionJobHandler.DistCpJobHandler.create(settings));
+ this.actionJobHandlerMap.set("ssh",actionJobHandler.SshActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("email",actionJobHandler.EmailActionJobHandler.create(settings));
+ this.actionJobHandlerMap.set("fs",actionJobHandler.FSActionJobHandler.create(settings));
+ },
+ getActionType(json){
+ var self=this;
+ var resolvedType=null;
+ var problaleActionsTypes=[];
+ Object.keys(json).forEach(function functionName(key) {
+ if (!self.validStandardActionProps.contains(key) && !key.startsWith("_")){
+ problaleActionsTypes.push(key);
+ }
+ });
+ if (problaleActionsTypes.length===1){
+ return problaleActionsTypes[0];
+ }else{
+ console.error("Invalid Action spec..",json);
+ }
+ return resolvedType;
+ },
+ getActionJobHandler(jobType){
+ return this.actionJobHandlerMap.get(jobType);
+ }
+});
+
+export {ActionTypeResolver};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
index 33204ea..2ce0ab4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/actionjob_hanlder.js
@@ -44,6 +44,7 @@ var ActionJobHandler=Ember.Object.extend(MappingMixin,{
}
this.handleMapping(nodeDomain,actionObj,this.mapping,nodeName);
},
+ /* jshint unused:vars */
validate(nodeDomain){
//overwrite in implmentations and return array of errors object.
},
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
new file mode 100644
index 0000000..957d1c0
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-generator.js
@@ -0,0 +1,55 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+var BundleGenerator= Ember.Object.extend({
+ x2js : new X2JS({useDoubleQuotes:true}),
+ bundle: null,
+ process (){
+ var xmlJson={"bundle-app":{}};
+ console.log(this.bundle);
+ var bundleApp=xmlJson["bundle-app"];
+ bundleApp._xmlns = "uri:oozie:bundle:0.1";
+ bundleApp._name = this.bundle.name;
+ if(!Ember.isEmpty(this.bundle.kickOffTime.value)){
+ bundleApp["control"] = {};
+ bundleApp["control"]["kick-off-time"] = this.bundle.kickOffTime.value;
+ }
+ this.generateCoordinatorsJson(bundleApp);
+ var xmlAsStr = this.get("x2js").json2xml_str(xmlJson);
+ return xmlAsStr;
+ },
+ generateCoordinatorsJson(bundleApp){
+ if (this.bundle.coordinators && this.bundle.coordinators.length>0){
+ bundleApp["coordinator"] = [];
+ this.bundle.coordinators.forEach((coordinator)=>{
+ var coordinatorJson = {"_name":coordinator.name};
+ coordinatorJson["app-path"] = coordinator.appPath;
+ if (coordinator.configuration &&
+ coordinator.configuration.property &&
+ coordinator.configuration.property.length > 0){
+ coordinatorJson["configuration"]={"property":[]};
+ var propertiesJson=coordinatorJson.configuration.property;
+ coordinator.configuration.property.forEach((prop) =>{
+ propertiesJson.push({"name" : prop.name, "value" : prop.value});
+ });
+ }
+ bundleApp["coordinator"].push(coordinatorJson);
+ }, this);
+ }
+ }
+});
+export {BundleGenerator};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
new file mode 100644
index 0000000..aa96221
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle-xml-importer.js
@@ -0,0 +1,87 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { Bundle } from '../bundle/bundle';
+
+var BundleXmlImporter= Ember.Object.extend({
+ x2js : new X2JS(),
+ importBundle (xml){
+ var bundleJson = this.get("x2js").xml_str2json(xml);
+ return this.processBundleXML(bundleJson);
+ },
+ processBundleXML(bundleJson){
+ var bundle = Bundle.create({
+ name : '',
+ kickOffTime : {
+ value : '',
+ displayValue : '',
+ type : 'date'
+ },
+ coordinators : Ember.A([])
+ });
+ var bundleApp=bundleJson["bundle-app"];
+ bundle.name = bundleApp._name;
+ if(bundleApp.control && bundleApp.control["kick-off-time"]) {
+ bundle.kickOffTime = this.extractDateField(bundleApp["control"]["kick-off-time"]);
+ }else{
+
+ }
+ this.processCoordinatorsJson(bundleApp, bundle);
+ return bundle;
+ },
+ processCoordinatorsJson(bundleApp, bundle){
+ if (bundleApp.coordinator){
+ bundle.coordinators = Ember.A([]);
+ if(Array.isArray(bundleApp.coordinator)){
+ bundleApp.coordinator.forEach((coordinator)=>{
+ bundle.coordinators.push(this.extractCoordinator(coordinator));
+ }, this);
+ }else{
+ bundle.coordinators.push(this.extractCoordinator(bundleApp.coordinator));
+ }
+ }
+ },
+ extractDateField(value){
+ var dateField = {};
+ var date = new Date(value);
+ dateField.value = value;
+ if(isNaN(date.getTime())){
+ dateField.displayValue = value;
+ dateField.type = 'expr';
+ }else{
+ dateField.type = 'date';
+ var utcDate = new Date(date.getTime() + date.getTimezoneOffset()*60*1000);
+ dateField.displayValue = moment(utcDate).format("MM/DD/YYYY hh:mm A");
+ }
+ return dateField;
+ },
+ extractCoordinator(coordinator) {
+ var coordinatorJson = {"name":coordinator._name};
+ coordinatorJson.appPath = coordinator["app-path"];
+ if (coordinator.configuration &&
+ coordinator.configuration.property &&
+ coordinator.configuration.property.length > 0){
+ coordinatorJson.configuration = {};
+ coordinatorJson.configuration.property = Ember.A([]);
+ coordinator.configuration.property.forEach(function(prop){
+ coordinatorJson.configuration.property.push({"name" : prop.name, "value" : prop.value});
+ });
+ }
+ return coordinatorJson;
+ }
+});
+export {BundleXmlImporter};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle.js
new file mode 100644
index 0000000..2b4bf59
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/bundle/bundle.js
@@ -0,0 +1,22 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+var Bundle = Ember.Object.extend({
+
+});
+export {Bundle};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
new file mode 100644
index 0000000..a657706
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-generator.js
@@ -0,0 +1,204 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+var CoordinatorGenerator= Ember.Object.extend({
+ x2js : new X2JS({useDoubleQuotes:true}),
+ coordinator: null,
+ init(){
+ },
+ process(){
+ var xmlJson={"coordinator-app":{}};
+ console.log(this.coordinator);
+ var coordinatorApp=xmlJson["coordinator-app"];
+ coordinatorApp._name = this.coordinator.name;
+ if(this.coordinator.frequency.type !== 'cron'){
+ coordinatorApp._frequency = "${coord:"+this.coordinator.frequency.type+"("+this.coordinator.frequency.value+")}";
+ }else{
+ coordinatorApp._frequency = this.coordinator.frequency.value;
+ }
+ coordinatorApp._start = this.coordinator.start.value;
+ coordinatorApp._end = this.coordinator.end.value;
+ coordinatorApp._timezone = this.coordinator.timezone;
+ coordinatorApp._xmlns = "uri:oozie:coordinator:0.4";
+ this.generateDataSets(coordinatorApp);
+ if(this.coordinator.dataInputType === 'simple'){
+ this.generateInputEvents(coordinatorApp);
+ }else{
+ this.generateConditionalInputEvents(coordinatorApp);
+ }
+ if(this.coordinator.inputLogic){
+ this.generateInputLogic(coordinatorApp);
+ }
+ this.generateOutputEvents(coordinatorApp);
+ this.generateAction(coordinatorApp);
+ this.generateParameters(coordinatorApp);
+ this.generateControls(coordinatorApp);
+ var xmlAsStr = this.get("x2js").json2xml_str(xmlJson);
+ return xmlAsStr;
+ },
+ generateDataSets(coordinatorApp){
+ if (this.coordinator.datasets && this.coordinator.datasets.length>0){
+ var datasets=[];
+ coordinatorApp["datasets"]={"dataset":datasets};
+ this.coordinator.datasets.forEach(function(dataset){
+ var dataSetJson={_name:dataset.name,
+ "_initial-instance":dataset.initialInstance.value,
+ _timezone:dataset.timezone
+ };
+ if(dataset.frequency.type !== 'cron'){
+ dataSetJson._frequency = "${coord:"+ dataset.frequency.type + "("+dataset.frequency.value + ")}";
+ }else{
+ dataSetJson._frequency = dataset.frequency.value;
+ }
+ dataSetJson["uri-template"]=dataset.uriTemplate;
+ if (dataset.doneFlag){
+ dataSetJson["done-flag"]=dataset.doneFlag;
+ }
+ datasets.push(dataSetJson);
+ });
+ }
+ },
+ generateInputEvents(coordinatorApp){
+ if (this.coordinator.dataInputs && this.coordinator.dataInputs.length>0){
+ coordinatorApp["input-events"]={"data-in":[]};
+ var dataInListJson=coordinatorApp["input-events"]["data-in"];
+ this.coordinator.dataInputs.forEach(function(datain){
+ var datainJson={_name:datain.name,_dataset:datain.dataset};
+ if (datain.instances && datain.instances.length>0){
+ var instancesJson=[];
+ datain.instances.forEach(function(instance){
+ if (instance&& instance.value){
+ instancesJson.push(instance.value);
+ }
+ });
+ datainJson["instance"]=instancesJson;
+ }else if (datain.start && datain.end){
+ datainJson["start-instance"]=datain.start.value;
+ datainJson["end-instance"]=datain.end.value;
+ }
+ dataInListJson.push(datainJson);
+ });
+ }
+ },
+ generateConditionalInputEvents(coordinatorApp){
+ if(this.coordinator.conditionalDataInput){
+ var condition = this.coordinator.conditionalDataInput;
+ coordinatorApp["input-events"] = {};
+ var inputEventJson = coordinatorApp["input-events"];
+ inputEventJson[condition.operator] = {};
+ var conditionJson = inputEventJson[condition.operator];
+ this.parseConditionTree(conditionJson, condition);
+ }
+ },
+ generateInputLogic(coordinatorApp){
+ var condition = this.coordinator.inputLogic;
+ coordinatorApp["input-logic"] = {};
+ var inputLogicJson = coordinatorApp["input-logic"];
+ inputLogicJson[condition.operator] = {};
+ var conditionJson = inputLogicJson[condition.operator];
+ this.parseConditionTree(conditionJson, condition);
+ },
+ parseConditionTree(conditionJson, condition){
+ if(!condition) {
+ return;
+ }
+ conditionJson._name = condition.name;
+ if(condition.min){
+ conditionJson._min = condition.min;
+ }
+ if(condition.wait){
+ conditionJson._wait = condition.wait;
+ }
+ if(condition.name){
+ conditionJson._name = condition.name;
+ }
+ if(!condition.operands){
+ return;
+ }
+ condition.operands.forEach((operand)=>{
+ if(operand.type === 'dataInput'){
+ if(!conditionJson["data-in"]){
+ conditionJson["data-in"] = [];
+ }
+ var dataInJson = {_dataset:operand.dataset};
+ if(operand.min){
+ dataInJson._min = operand.min;
+ }
+ if(operand.wait){
+ dataInJson._wait = operand.wait;
+ }
+ if(operand.name){
+ dataInJson._name = operand.name;
+ }
+ conditionJson["data-in"].push(dataInJson);
+ }else if(operand.type === 'condition'){
+ conditionJson[operand.operator] = {};
+ this.parseConditionTree(conditionJson[operand.operator], operand);
+ }
+ }, this);
+ },
+ generateOutputEvents(coordinatorApp){
+ if (this.coordinator.dataOutputs && this.coordinator.dataOutputs.length>0){
+ coordinatorApp["output-events"]={"data-out":[]};
+ var dataOutputsJson= coordinatorApp["output-events"]["data-out"];
+ this.coordinator.dataOutputs.forEach(function(dataOut){
+ var dataOutJson={_dataset:dataOut.dataset,_name:dataOut.name,instance:dataOut.instance.value};
+ dataOutputsJson.push(dataOutJson);
+ });
+ }
+ },
+ generateAction(coordinatorApp){
+ var actionJson={"workflow":{"app-path":this.coordinator.workflow.appPath}};
+ coordinatorApp.action=actionJson;
+ if (this.coordinator.workflow.configuration &&
+ this.coordinator.workflow.configuration.property &&
+ this.coordinator.workflow.configuration.property.length>0){
+ actionJson.workflow["configuration"]={"property":[]};
+ var propertiesJson=actionJson.workflow.configuration.property;
+ this.coordinator.workflow.configuration.property.forEach(function(prop){
+ propertiesJson.push({"name":prop.name,"value":prop.value});
+ });
+ }
+ },
+ generateParameters(coordinatorApp){
+ if (this.coordinator.parameters.configuration &&
+ this.coordinator.parameters.configuration.property &&
+ this.coordinator.parameters.configuration.property.length>0){
+ coordinatorApp["parameters"] = {};
+ var paramJson = coordinatorApp["parameters"];
+ paramJson["configuration"]={"property":[]};
+ var propertiesJson=paramJson.configuration.property;
+ this.coordinator.parameters.configuration.property.forEach(function(prop){
+ propertiesJson.push({"name":prop.name,"value":prop.value});
+ });
+ }
+ },
+ generateControls(coordinatorApp) {
+ if(this.coordinator.controls && this.coordinator.controls.length > 0){
+ coordinatorApp["controls"] = {};
+ this.coordinator.controls.forEach((control)=>{
+ if(control.value){
+ coordinatorApp["controls"][control.name] = control.value;
+ }
+ }, this);
+ if(Object.keys(coordinatorApp["controls"]).length === 0){
+ delete coordinatorApp["controls"];
+ }
+ }
+ }
+ });
+ export {CoordinatorGenerator};
[06/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
new file mode 100644
index 0000000..fca90b3
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator-xml-importer.js
@@ -0,0 +1,272 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import { Coordinator } from '../coordinator/coordinator';
+
+var CoordinatorXmlImporter= Ember.Object.extend({
+ x2js : new X2JS(),
+ importCoordinator (xml){
+ var coordinatorJson = this.get("x2js").xml_str2json(xml);
+ return this.processCoordinatorXML(coordinatorJson);
+ },
+ createNewCoordinator(){
+ return Coordinator.create({
+ workflow : {
+ appPath : '',
+ configuration :{
+ property : Ember.A([])
+ }
+ },
+ frequency : {
+ type : '',
+ value : ''
+ },
+ start : {
+ value : '',
+ displayValue : '',
+ type : 'date'
+ },
+ end : {
+ value : '',
+ displayValue : '',
+ type : 'date'
+ },
+ timezone : '',
+ datasets : Ember.A([]),
+ dataInputs : Ember.A([]),
+ dataOutputs : Ember.A([]),
+ dataInputType : 'simple',
+ parameters : {
+ configuration :{
+ property : Ember.A([])
+ }
+ },
+ controls : Ember.A([])
+ });
+ },
+ processCoordinatorXML(coordinatorJson){
+ var coordinatorApp = coordinatorJson["coordinator-app"];
+ var coordinator = this.createNewCoordinator();
+ coordinator.name = coordinatorApp._name;
+ var frequency = coordinatorApp._frequency;
+ if(frequency.startsWith('${coord:')){
+ coordinator.frequency.type = frequency.substring(frequency.indexOf(':')+1, frequency.indexOf('('));
+ coordinator.frequency.value = frequency.substring(frequency.indexOf('(')+1, frequency.indexOf(')'));
+ }else{
+ coordinator.frequency.type = 'cron';
+ coordinator.frequency.value = frequency;
+ }
+ coordinator.start = this.extractDateField(coordinatorApp._start);
+ coordinator.end = this.extractDateField(coordinatorApp._end);
+ coordinator.timezone = coordinatorApp._timezone;
+ this.extractDataSets(coordinatorApp, coordinator);
+ if(coordinatorApp['input-events'] && coordinatorApp['input-events']['data-in']){
+ coordinator.dataInputType = 'simple';
+ this.extractInputEvents(coordinatorApp, coordinator);
+ }else{
+ coordinator.dataInputType = 'logical';
+ coordinator.supportsConditionalDataInput = true;
+ this.extractLogicalInputEvents(coordinatorApp, coordinator);
+ }
+ this.extractOutputEvents(coordinatorApp, coordinator);
+ this.extractAction(coordinatorApp, coordinator);
+ this.extractParameters(coordinatorApp, coordinator);
+ this.extractControls(coordinatorApp, coordinator);
+ return coordinator;
+ },
+ extractDateField(value){
+ var dateField = {};
+ var date = new Date(value);
+ dateField.value = value;
+ if(isNaN(date.getTime())){
+ dateField.displayValue = value;
+ dateField.type = 'expr';
+ }else{
+ dateField.type = 'date';
+ var utcDate = new Date(date.getTime() + date.getTimezoneOffset()*60*1000);
+ dateField.displayValue = moment(utcDate).format("MM/DD/YYYY hh:mm A");
+ }
+ return dateField;
+ },
+ extractDataSet(dataset){
+ var dataSetJson = {
+ name : dataset._name,
+ frequency : {},
+ initialInstance :this.extractDateField( dataset['_initial-instance']),
+ timezone : dataset._timezone
+ };
+ var frequency = dataset._frequency;
+ if(frequency.startsWith('${coord:')){
+ dataSetJson.frequency.type = frequency.substring(frequency.indexOf(':')+1, frequency.indexOf('('));
+ dataSetJson.frequency.value = frequency.substring(frequency.indexOf('(')+1, frequency.indexOf(')'));
+ }else{
+ dataSetJson.frequency.type = 'cron';
+ dataSetJson.frequency.value = frequency;
+ }
+ dataSetJson["uriTemplate"] = dataset['uri-template'];
+ if (dataset['done-flag']){
+ dataSetJson.doneFlag = dataset['done-flag'];
+ }
+ return dataSetJson;
+ },
+ extractDataSets(coordinatorApp, coordinator){
+ if (coordinatorApp.datasets && coordinatorApp.datasets.dataset){
+ if(Array.isArray(coordinatorApp.datasets.dataset)) {
+ coordinatorApp.datasets.dataset.forEach(function(dataset){
+ coordinator.datasets.push(this.extractDataSet(dataset));
+ }, this);
+ }else{
+ coordinator.datasets.push(this.extractDataSet(coordinatorApp.datasets.dataset));
+ }
+ }
+ },
+ extractDataInput(datain){
+ var datainJson = {
+ name : datain._name,
+ dataset : datain._dataset
+ };
+ if (datain.instance && datain.instance.length>0){
+ datainJson.instances = Ember.A([]);
+ if(Array.isArray(datain.instance)) {
+ datain.instance.forEach(function(instance){
+ datainJson.instances.pushObject(this.extractDateField(instance));
+ }, this);
+ }else{
+ datainJson.instances.pushObject(this.extractDateField(datain.instance));
+ }
+ datainJson.isList = true;
+ }else if (datain["start-instance"] && ["end-instance"]){
+ datainJson.start = this.extractDateField(datain["start-instance"]);
+ datainJson.end = this.extractDateField(datain["end-instance"]);
+ datainJson.isList = false;
+ }
+ return datainJson;
+ },
+ extractInputEvents(coordinatorApp, coordinator){
+ if(Array.isArray(coordinatorApp['input-events']['data-in'])){
+ coordinatorApp['input-events']['data-in'].forEach(function(datain){
+ coordinator.dataInputs.push(this.extractDataInput(datain));
+ }, this);
+ }else{
+ coordinator.dataInputs.push(this.extractDataInput(coordinatorApp['input-events']['data-in']));
+ }
+ },
+ extractLogicalInputEvents(coordinatorApp, coordinator){
+ var conditionJson = coordinatorApp['input-events'];
+ var condition = {};
+ coordinator.conditionalDataInput = condition;
+ Object.keys(conditionJson).forEach((key)=>{
+ condition.operator = key;
+ this.parseConditionTree(conditionJson[key], condition);
+ }, this);
+ },
+ extractDataInputOperand(operandJson){
+ var operand = {};
+ operand.name = operandJson._name;
+ operand.type = 'dataInput';
+ operand.dataset = operandJson._dataset;
+ if(operandJson._min) {
+ operand.min = operandJson._min;
+ }
+ if(operandJson._wait) {
+ operand.wait = operandJson._wait;
+ }
+ return operand;
+ },
+ parseConditionTree(conditionJson, condition) {
+ condition.name = conditionJson._name;
+ condition.operands = Ember.A([]);
+ Object.keys(conditionJson).forEach( (key) => {
+ var operandsJson = conditionJson[key];
+ if(key === 'data-in') {
+ if(Array.isArray(operandsJson) ) {
+ operandsJson.forEach((json) => {
+ condition.operands.pushObject(this.extractDataInputOperand(json));
+ }, this);
+ }else{
+ condition.operands.pushObject(this.extractDataInputOperand(operandsJson));
+ }
+ }else if(key !== '_name') {
+ var operand = {};
+ operand.operator = key;
+ operand.type = 'condition';
+ condition.operands.pushObject(operand);
+ this.parseConditionTree(operandsJson, operand);
+ }
+ }, this);
+ },
+ extractDataOutput(dataOutJson){
+ return {
+ dataset:dataOutJson._dataset,
+ name:dataOutJson._name,
+ instance:this.extractDateField(dataOutJson.instance)
+ };
+ },
+ extractOutputEvents(coordinatorApp, coordinator){
+ if (coordinatorApp['output-events'] && coordinatorApp['output-events']['data-out']){
+ var dataOutputsJson = coordinatorApp["output-events"]["data-out"];
+ if(Array.isArray(dataOutputsJson)){
+ dataOutputsJson.forEach(function(dataOutJson){
+ coordinator.dataOutputs.pushObject(this.extractDataOutput(dataOutJson));
+ }, this);
+ }else{
+ coordinator.dataOutputs.pushObject(this.extractDataOutput(dataOutputsJson));
+ }
+ }
+ },
+ extractAction(coordinatorApp, coordinator){
+ var actionJson = coordinatorApp['action']['workflow'];
+ coordinator.workflow.appPath = actionJson['app-path'];
+ if(actionJson.configuration && actionJson.configuration.property){
+ if(Array.isArray(actionJson.configuration.property)){
+ actionJson.configuration.property.forEach(function(prop){
+ coordinator.workflow.configuration.property.push(this.extractConfigProperty(prop));
+ }, this);
+ }else{
+ coordinator.workflow.configuration.property.push(this.extractConfigProperty(actionJson.configuration.property));
+ }
+
+ }
+ },
+ extractConfigProperty(propJson){
+ return {"name" : propJson.name, "value" : propJson.value};
+ },
+ extractParameters(coordinatorApp, coordinator){
+ var paramJson = coordinatorApp['parameters'];
+ if(!paramJson) {
+ return;
+ }
+ if(paramJson.configuration && paramJson.configuration.property){
+ if(Array.isArray(paramJson.configuration.property)){
+ paramJson.configuration.property.forEach(function(prop){
+ coordinator.parameters.configuration.property.push(this.extractConfigProperty(prop));
+ }, this);
+ }else{
+ coordinator.parameters.configuration.property.push(this.extractConfigProperty(paramJson.configuration.property));
+ }
+ }
+ },
+ extractControls(coordinatorApp, coordinator) {
+ var controls = coordinatorApp["controls"];
+ if(controls && Object.keys(controls).length > 0){
+ Object.keys(controls).forEach((controlName)=>{
+ coordinator.controls.pushObject({'name':controlName, 'value':controls[controlName]});
+ }, this);
+ }
+ }
+});
+export { CoordinatorXmlImporter };
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator.js
new file mode 100644
index 0000000..58396d7
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/coordinator/coordinator.js
@@ -0,0 +1,22 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+var Coordinator = Ember.Object.extend({
+
+});
+export {Coordinator};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
new file mode 100644
index 0000000..086916f
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-flow-renderer.js
@@ -0,0 +1,348 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+import CytoscapeStyles from '../domain/cytoscape-style';
+var CytoscapeRenderer= Ember.Object.extend({
+ currentCyNode: null,
+ staticNodes: ['start', 'end', 'join', 'placeholder'],
+ dataNodes: [],
+ cyOverflow: {},
+ cy: null,
+ layoutConfigs: { name: 'dagre', fit: false, edgeSep: 100 },
+ _initCY(settings){
+ this.get("context").$('#'+this.id).height(settings.canvasHeight);
+ this.cy = cytoscape({
+ container: this.get("context").$('#'+this.id),
+ elements: [],
+ style: CytoscapeStyles.style,
+ layout: this.get("layoutConfigs")
+ });
+
+ // the default values of each option are outlined below:
+ var defaults = {
+ zoomFactor: 2.0, // zoom factor per zoom tick
+ minZoom: 0.1, // min zoom level
+ maxZoom: 10, // max zoom level
+
+ // icon class names
+ sliderHandleIcon: 'fa fa-minus',
+ zoomInIcon: 'fa fa-plus',
+ zoomOutIcon: 'fa fa-minus',
+ resetIcon: 'fa fa-expand'
+ };
+
+ this.cy.panzoom( defaults );
+ //this.cy.center();
+ this.cy.pan({x:200,y:50});
+ this._addEvents(this.cy);
+ var self = this;
+ this.get("context").$('.overlay-transition-content').popover({
+ html : true,
+ title : "Add Node <button type='button' class='close'>×</button>",
+ placement: 'right',
+ trigger : 'focus',
+ content : function(){
+ return self.get("context").$('#workflow-actions').html();
+ }
+ });
+
+ this.get("context").$("#cyRenderer").on('click','.popover .close',function(){
+ this.get("context").$('.popover').popover('hide');
+ }.bind(this));
+ },
+ _setCyOverflow() {
+ Ember.set(this.get("cyOverflow"), "overflown", this.cy.elements().renderedBoundingBox().y2 > this.cy.height());
+ },
+ _getShape(nodeType) {
+ switch(nodeType) {
+ case 'start' :
+ case 'end' :
+ case 'kill' :
+ case 'placeholder' :
+ return 'ellipse';
+ case 'action' :
+ return 'roundrectangle';
+ case 'fork' :
+ case 'join' :
+ return 'rectangle';
+ case 'decision' :
+ return 'diamond';
+ default :
+ return 'star';
+ }
+ },
+
+ _getCyDataNodes(workflow){
+ this.get('dataNodes').clear();
+ var self=this;
+ workflow.nodeVisitor.process(workflow.startNode, function(node) {
+ if (node.type === 'kill') {
+ return;
+ }
+ self.get('dataNodes').pushObject({
+ data: {
+ id: node.id, name: node.name, type: node.type,
+ shape: self._getShape(node.type),
+ node: node
+ },
+ dataNodeName: Ember.computed.alias('data.node.name')
+ });
+ if (node.transitions.length > 0) {
+ node.transitions.forEach(function(transition){
+ if (transition.isOnError()){
+ return;
+ }
+ self.get('dataNodes').pushObject(
+ {
+ data: {
+ id: transition.sourceNodeId + '_to_' + transition.targetNode.id,
+ source:transition.sourceNodeId,
+ target: transition.targetNode.id,
+ transition: transition,
+ transitionCount: node.getOkTransitionCount()
+ }
+ }
+ );
+ });
+ }
+ });
+ },
+
+ _showNodeEditor(node, nodeObj){
+ if (nodeObj && this.get("currentCyNode") && (nodeObj.data().id === this.get("currentCyNode").data().id)) {
+ if (this.staticNodes.contains(node.data().type)) {
+ return;
+ }
+ this.get("context").$("#"+ node.data().id + " :input").show();
+ this.get("context").$("#"+ node.data().id + " :input").css({
+ top: nodeObj.renderedPosition().y - (nodeObj.outerHeight()/2),
+ left: nodeObj.renderedPosition().x - (nodeObj.outerWidth()/2)
+ });
+ }
+ this.set("currentCyNode", nodeObj);
+ },
+
+ _showNodeTooltip(event){
+ var node = event.cyTarget;
+ var nodeObj = this.cy.$('#' + node.id());
+ if (this.staticNodes.contains(node.data().type)) {
+ return;
+ }
+ this.get("context").$(".overlay-node-label").css({
+ top: nodeObj.renderedPosition().y - (nodeObj.outerHeight() - ((node.data().type === 'decision')?20:0)),
+ left: nodeObj.renderedPosition().x + (nodeObj.outerWidth()/2 - 30)
+ });
+ this.get("context").$(".overlay-node-label").text(node.data().node.name);
+ this.get("context").$(".overlay-node-label").show();
+ },
+
+ _addEvents(cy){
+ cy.on('pan', function() {
+ this.get("context").$(".overlay_node_editor, .overlay-node-actions, .overlay-fork-icon, .overlay-trash-icon, .overlay-settings-icon").hide();
+ this.get("context").$(".overlay-transition-content").hide();
+ this._setCyOverflow();
+ }.bind(this));
+
+ cy.on('click', function(event) {
+ if (event.cyTarget === cy) {
+ this.get("context").$(".overlay_node_editor, .overlay-node-actions, .overlay-fork-icon, .overlay-trash-icon, .overlay-settings-icon").hide();
+ this.get("context").$(".overlay-transition-content").hide();
+ }
+ }.bind(this));
+
+ cy.on('mousemove', 'node', function(event) {
+ event.cyTarget.css({'border-color': '#5bb75b'});
+ this.get("context").actionInfo(event.cyTarget.data().node);
+ this._showNodeTooltip(event);
+ }.bind(this));
+
+ cy.on('mouseout', 'node',function(event) {
+ event.cyTarget.css({'border-color': '#ABABAB'});
+ this.get("context").$(".overlay-node-label").hide();
+ }.bind(this));
+
+ cy.on('mousemove', 'edge', function(event) {
+ event.cyTarget.css({'line-color': '#5bb75b', 'target-arrow-color': '#5bb75b'});
+ }.bind(this));
+
+ cy.on('mouseout', 'edge',function(event) {
+ event.cyTarget.css({'line-color': '#ABABAB', 'target-arrow-color': '#ABABAB'});
+ }.bind(this));
+
+ cy.on('click', 'node', function(event) {
+ this.get("context").$(".overlay-node-actions span").hide();
+ this.get("context").$(".overlay-transition-content").hide();
+ var node = event.cyTarget;
+ var nodeObj = cy.$('#' + node.id());
+ this._showNodeEditor(node, nodeObj);
+ if (!(node.data().type === 'start' || node.data().type === 'end' || node.data().type === 'placeholder')) {
+ this.get("context").$(".overlay-node-actions, .overlay-trash-icon").show();
+ }
+ if (node.data().type === 'action' || node.data().type === 'decision') {
+ this.get("context").$(".overlay-settings-icon").show();
+ }
+ if (node.data().type === 'action') {
+ this.get("context").$(".overlay-copy-icon").show();
+ this.get("context").$(".overlay-cut-icon").show();
+ if(this.get('context').get('clipboard')){
+ this.get("context").$(".overlay-paste-icon").show();
+ }
+ }
+ if (node.data().type === 'fork' || node.data().type === 'decision') {
+ this.get("context").$(".overlay-fork-icon").show();
+ }
+ this.get("context").$(".overlay-node-actions").css({
+ top: nodeObj.renderedPosition().y - (nodeObj.outerHeight()) + 20,
+ left: nodeObj.renderedPosition().x + (nodeObj.outerWidth()/3) + 50
+ });
+ this.get("context").$(".overlay-trash-icon, .overlay-fork-icon, .overlay-settings-icon, .overlay-copy-icon, .overlay-paste-icon, .overlay-cut-icon").data("node", node.data().node);
+ }.bind(this));
+
+ cy.on('click', 'edge', function(event) {
+ this.get("context").$(".decision-condition-label").hide();
+ this.get("context").$(".overlay-transition-content").hide();
+ this.get("context").$(".overlay_node_editor, .overlay-node-actions, .overlay-fork-icon, .overlay-trash-icon, .overlay-settings-icon").hide();
+ this.get("context").$(".overlay-transition-content").show();
+ this.get("context").$(".overlay-transition-content").css({
+ top: event.originalEvent.offsetY + 10,
+ left: event.originalEvent.offsetX + 15
+ });
+ if (event.cyTarget.data().transitionCount>1){
+ this.get("context").$(".overlay-trash-transition-icon").show();
+ }else{
+ this.get("context").$(".overlay-trash-transition-icon").hide();
+ }
+ this.get("context").$(".overlay-transition-content").data("transition",event.cyTarget.data().transition);
+
+ if (event.cyTarget.data().transition && event.cyTarget.data().transition.condition) {
+ this.get("context").$(".decision-condition-body").html(event.cyTarget.data().transition.condition);
+ this.get("context").$(".decision-condition-label").css({
+ top: event.originalEvent.offsetY,
+ left: event.originalEvent.offsetX + 10
+ });
+ this.get("context").$(".decision-condition-label").show();
+ }
+ }.bind(this));
+
+ this.get("context").$('.overlay-plus-icon').off('click');
+ this.get("context").$('.overlay-plus-icon').on('click',function(){
+ this.get("context").$(".overlay-transition-content").popover("show");
+ this.get("context").set('popOverElement', this.get("context").$('.overlay-transition-content'));
+ this.get("context").setCurrentTransition(this.get("context").$(".overlay-transition-content").data("transition"));
+ Ember.run.later(this, function() {
+ this.get("context").$('.overlay-transition-content').hide();
+ }, 1000);
+ }.bind(this));
+
+ this.get("context").$('.overlay-trash-transition-icon').off('click');
+ this.get("context").$('.overlay-trash-transition-icon').on('click',function(){
+ this.get("context").deleteTransition(this.get("context").$(".overlay-transition-content").data("transition"));
+ this.get("context").$('.overlay-transition-content').hide();
+ }.bind(this));
+
+ this.get("context").$('.overlay-trash-icon i').off('click');
+ this.get("context").$('.overlay-trash-icon i').on('click',function(){
+ this.get("context").deleteWorkflowNode(this.get("context").$(".overlay-trash-icon").data("node"));
+ this.get("context").$('.overlay-node-actions').hide();
+ }.bind(this));
+
+ this.get("context").$('.overlay-copy-icon i').off('click');
+ this.get("context").$('.overlay-copy-icon i').on('click',function(){
+ this.get("context").copyNode(this.get("context").$(".overlay-copy-icon").data("node"));
+ this.get("context").$('.overlay-node-actions').hide();
+ }.bind(this));
+
+ this.get("context").$('.overlay-paste-icon i').off('click');
+ this.get("context").$('.overlay-paste-icon i').on('click',function(){
+ this.get("context").replaceNode(this.get("context").$(".overlay-paste-icon").data("node"));
+ this.get("context").$('.overlay-node-actions').hide();
+ }.bind(this));
+
+ this.get("context").$('.overlay-cut-icon i').off('click');
+ this.get("context").$('.overlay-cut-icon i').on('click',function(){
+ this.get("context").cutNode(this.get("context").$(".overlay-cut-icon").data("node"));
+ this.get("context").$('.overlay-node-actions').hide();
+ }.bind(this));
+
+ this.get("context").$('.overlay-fork-icon i').off('click');
+ this.get("context").$('.overlay-fork-icon i').on('click',function(){
+ var node = this.get("context").$(".overlay-fork-icon").data("node");
+
+ if (node.isDecisionNode()) {
+ this.get("context").openDecisionEditor(this.get("context").$(".overlay-fork-icon").data("node"));
+ this.get("context").$("#selector-content").css({
+ top: this.get("currentCyNode").renderedPosition().y - (this.get("currentCyNode").outerHeight()),
+ left: this.get("currentCyNode").renderedPosition().x + (this.get("currentCyNode").outerWidth()/2)
+ });
+ } else if (node.isForkNode()) {
+ this.get("context").addWorkflowBranch(this.get("context").$(".overlay-fork-icon").data("node"));
+ }
+ this.get("context").$('.overlay-node-actions').hide();
+ }.bind(this));
+
+ this.get("context").$('.overlay-settings-icon i').off('click');
+ this.get("context").$('.overlay-settings-icon i').on('click',function(){
+ this.get("context").openWorkflowEditor(this.get("context").$(".overlay-settings-icon").data("node"));
+ this.get("context").$('.overlay-node-actions').hide();
+ }.bind(this));
+ },
+
+ renderWorkflow(workflow){
+ this._getCyDataNodes(workflow);
+ this.cy.$('node').remove();
+ this.cy.add(this.get('dataNodes'));
+ this.cy.layout(this.get("layoutConfigs"));
+ this._setCyOverflow();
+ },
+
+ initRenderer(callback, settings){
+ this.context=settings.context;
+ this.dataNodes=settings.dataNodes;
+ this.cyOverflow=settings.cyOverflow;
+ this._initCY(settings);
+ callback();
+ },
+ reset(){
+
+ },
+ resetLayout() {
+ this.cy.layout();
+ },
+ refresh(){
+
+ },
+ onDidUpdate(){
+ return true;
+ },
+ cleanup(){
+ },
+ resize(){
+ if (this.cy){
+ Ember.run.later(this, function() {
+ this.cy.resize();
+ },50);
+ }
+ },
+ getBottomPosition() {
+ return {
+ top: this.get("context").$('#'+this.id).offset().top + this.get("context").$('#'+this.id).height,
+ left: this.get("context").$('#'+this.id).offset().left + 100
+ };
+ }
+});
+export {CytoscapeRenderer};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
new file mode 100644
index 0000000..92820f9
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/cytoscape-style.js
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+var defaultNodeColor = '#fff';
+var actionNodeColor = '#f5f5f5';
+export default Ember.Object.create({
+ style: [
+ {
+ selector: 'node',
+ style: {
+ shape: 'data(shape)',
+ 'background-color': defaultNodeColor,
+ 'border-width': 1,
+ 'border-color': '#ABABAB',
+ //'text-margin-x': 10,
+ label: function(target) {
+ if (!target.data().node.name) {
+ return "";
+ } else if (target.data().node.name.length>12){
+ return target.data().node.name.slice(0, 12)+"...";
+ } else{
+ return target.data().node.name;
+ }
+ },
+ 'text-valign': 'center',
+ 'font-size': 14,
+ height: 40,
+ width: 40
+ }
+ },
+ {
+ selector: 'node[type = "fork"]',
+ style: {
+ 'background-image': 'assets/sitemap.png',
+ 'background-position-x': 10,
+ width: 150
+ }
+ },
+ {
+ selector: 'node[type = "join"]',
+ style: {
+ 'background-image': 'assets/join.png',
+ label: '',
+ width: 80
+ }
+ },
+ {
+ selector: 'node[type = "decision"]',
+ style: {
+ height: 60,
+ width: 120
+ }
+ },
+ {
+ selector: 'node[type = "start"]',
+ style: {
+ 'background-image': 'assets/play.png',
+ label: ''
+ }
+ },
+ {
+ selector: 'node[type = "end"]',
+ style: {
+ 'background-image': 'assets/stop.png',
+ label: ''
+ }
+ },
+ {
+ selector: 'node[type = "placeholder"]',
+ style: {
+ width: 1,
+ height: 1,
+ label: ''
+ }
+ },
+ {
+ selector: 'node[type = "action"]',
+ style: {
+ 'background-color': actionNodeColor,
+ width: 150
+ }
+ },
+ {
+ selector: 'edge',
+ style: {
+ 'curve-style': 'bezier',
+ 'target-arrow-shape': function(target){
+ if (target.data().transition && target.data().transition.getTargetNode(false) && !target.data().transition.getTargetNode(false).isPlaceholder()) {
+ return "triangle";
+ }else{
+ return "none";
+ }
+ },
+ width: 1,
+ 'font-size': 12,
+ label: function(target) {
+ if (!target.data().transition || !target.data().transition.condition) {
+ return "";
+ }else if (target.data().transition.condition.length>5){
+ return target.data().transition.condition.slice(0, 5)+"...";
+ }else{
+ return target.data().transition.condition;
+ }
+ }
+ }
+ }
+ ]
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/default-layout-manager.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/default-layout-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/default-layout-manager.js
index e208f83..b7121f4 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/default-layout-manager.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/default-layout-manager.js
@@ -17,13 +17,13 @@
import Ember from 'ember';
var DefaultLayoutManager= Ember.Object.extend({
- doDagreLayout(nodes,edges){
+ doDagreLayout(component, nodes,edges){
var g = new dagre.graphlib.Graph();
g.setGraph({rankdir:"TB", nodesep:100,edgesep:200,marginx:40,ranksep:130});
g.setDefaultEdgeLabel(function() { return {}; });
for (var i = 0; i < nodes.length; i++) {
- var n = Ember.$(nodes[i]);
+ var n = component.$(nodes[i]);
g.setNode(n.attr("id"), {width: n.width(), height: n.height()});
}
@@ -35,13 +35,13 @@ var DefaultLayoutManager= Ember.Object.extend({
return g;
},
doLayout(component,nodes,edges){
- var g=this.doDagreLayout(nodes,edges);
+ var g=this.doDagreLayout(component, nodes,edges);
g.nodes().forEach(function(v) {
try{
var nodeWidth=component.$("#" + v).width();
var displacement=150-Math.floor(nodeWidth/2);
- Ember.$("#" + v).css("left", g.node(v).x+displacement + "px");
- Ember.$("#" + v).css("top",g.node(v).y+ "px");
+ component.$("#" + v).css("left", g.node(v).x+displacement + "px");
+ component.$("#" + v).css("top",g.node(v).y+ "px");
}catch(err){
}
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/findnode-mixin.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/findnode-mixin.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/findnode-mixin.js
index 0566e06..c770fb0 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/findnode-mixin.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/findnode-mixin.js
@@ -18,22 +18,65 @@
import Ember from 'ember';
var FindNodeMixin= Ember.Mixin.create({
findNodeById(startNode,id){
-
- return this.findNodeByIdInternal(startNode,id);
+ return this._findNodeById(startNode,id);
+ },
+ findTransition(startNode,sourceId,targetId){
+ return this._findTransition(startNode,sourceId,targetId);
+ },
+ _findTransition(node,sourceId,targetId){
+ if (!node.transitions){
+ return null;
+ }
+ var res;
+ for (var i = 0; i < node.transitions.length; i++) {
+ var tran= node.transitions[i];
+ if (node.id===sourceId && tran.getTargetNode(false).id===targetId){
+ res=tran;
+ }else{
+ res=this._findTransition(tran.getTargetNode(false),sourceId,targetId);
+ }
+ if (res){
+ break;
+ }
+ }
+ return res;
+ },
+ findTransitionTo(startNode,nodeid){
+ return this._findTransitionTo(startNode,nodeid);
+ },
+ _findTransitionTo(node,nodeid){
+ if (!node.transitions){
+ return null;
+ }
+ var res;
+ for (var i = 0; i < node.transitions.length; i++) {
+ var tran= node.transitions[i];
+ if (tran.getTargetNode(false).id===nodeid){
+ res=tran;
+ }else{
+ res=this._findTransitionTo(tran.getTargetNode(false),nodeid);
+ }
+ if (res){
+ break;
+ }
+ }
+ return res;
},
- findNodeByIdInternal(node,id){
+ _findNodeById(node,id){
var self=this;
if (node.get("id")===id){
return node;
}else{
if (node.transitions){
+ var res;
for (var i = 0; i < node.transitions.length; i++) {
var transition=node.transitions[i];
- var result=self.findNodeByIdInternal(transition.getTargetNode(true),id);
- if (result){
- return result;
+ res= self._findNodeById(transition.getTargetNode(false),id);
+ if (res){
+ break;
}
}
+ return res;
}else{
return null;
}
@@ -63,7 +106,7 @@ var FindNodeMixin= Ember.Mixin.create({
for(var i =0; i< nxtPath.length; i++){
currNode = nxtPath[i];
do {
- if(this.insertUniqueNodes(currNode, nodes) && currNode){
+ if(this._insertUniqueNodes(currNode, nodes) && currNode){
nodes.push(currNode);
}
var nodesList = currNode.getTargets();
@@ -74,7 +117,7 @@ var FindNodeMixin= Ember.Mixin.create({
if(tmp.length){
nodes = nodes.concat(tmp);
}
- } else if(this.insertUniqueNodes(nodesList[j], nodes) && nodesList[j]){
+ } else if(this._insertUniqueNodes(nodesList[j], nodes) && nodesList[j]){
nodes.push(nodesList[j]);
currNode = nodesList[j];
} else {
@@ -91,7 +134,7 @@ var FindNodeMixin= Ember.Mixin.create({
}
return nodes;
},
- insertUniqueNodes(currNode, nodes){
+ _insertUniqueNodes(currNode, nodes){
if(nodes.indexOf(currNode) > -1){
} else {
if (!( currNode.isKillNode() || currNode.isPlaceholder() || currNode.isJoinNode() || currNode.isDecisionEnd())){
@@ -99,5 +142,57 @@ var FindNodeMixin= Ember.Mixin.create({
}
}
},
+ _findCommonTargetNodeId(node){
+ var nodeIds = {}, targ, decPath = node.getTargets(), tempId = 0;
+ for(var i =0; i< decPath.length; i++){
+ var currNode = decPath[i];
+ do {
+ if(nodeIds.hasOwnProperty(currNode.get("id"))){
+ nodeIds[currNode.get("id")] = nodeIds[currNode.get("id")] + 1;
+ } else {
+ nodeIds[currNode.get("id")] = 1;
+ }
+ if(currNode.get("id") === "node-end"){
+ break;
+ }
+ currNode = currNode.getTargets()[0];
+ } while(currNode && currNode.get("id"));
+ }
+ for(var j in nodeIds){
+ if(tempId < nodeIds[j]){
+ targ = j;
+ tempId = nodeIds[j];
+ }
+ }
+ return targ;
+ },
+ _findCommonTargetNode(node){
+ var nodeIds = {}, targ, decPath = node.getTargets(), tempId = 0;
+ for(var i =0; i< decPath.length; i++){
+ var currNode = decPath[i];
+ do {
+ if(nodeIds.hasOwnProperty(currNode.get("id"))){
+ nodeIds[currNode.get("id")] = nodeIds[currNode.get("id")] + 1;
+ } else {
+ nodeIds[currNode.get("id")] = 1;
+ }
+ if(currNode.get("id") === "node-end"){
+ break;
+ }
+ currNode = currNode.getTargets()[0];
+ } while(currNode && currNode.get("id"));
+ }
+ for(var j in nodeIds){
+ if(tempId < nodeIds[j]){
+ targ = j;
+ tempId = nodeIds[j];
+ }
+ }
+ return targ;
+ },
+ findCommonTargetNode(startNode,node){
+ var commonTargetId=this._findCommonTargetNodeId(node);
+ return this.findNodeById(startNode,commonTargetId);
+ }
});
export{FindNodeMixin};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/id-gen.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/id-gen.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/id-gen.js
index 0ee985e..ccbfcc3 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/id-gen.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/id-gen.js
@@ -29,6 +29,10 @@ var IdGen = Ember.Object.extend({
reset(){
this.nameCount=0;
this.idCount=0;
+ },
+ resetTo(val){
+ this.nameCount=val;
+ this.idCount=val;
}
});
var idGen=IdGen.create({});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/jsplumb-flow-renderer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/jsplumb-flow-renderer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/jsplumb-flow-renderer.js
new file mode 100644
index 0000000..c3e3133
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/jsplumb-flow-renderer.js
@@ -0,0 +1,194 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+import Constants from '../utils/constants';
+import {DefaultLayoutManager as LayoutManager} from '../domain/default-layout-manager';
+var JSPlumbRenderer= Ember.Object.extend({
+ designerPlumb:null,
+ flattenedNodes:null,
+ _createConnection(sourceNode,target,transition){
+ var connectionColor="#777";
+ var lineWidth=1;
+ if (transition.condition){
+ if(transition.condition==="default"){
+ lineWidth=2;
+ }else if (transition.condition==="error"|| transition.errorPath){
+ connectionColor=Constants.globalSetting.errorTransitionColor;
+ }
+ }
+ var connectionObj={
+ source:sourceNode.id,
+ target:target.id,
+ connector:["Straight"],
+ paintStyle:{lineWidth:lineWidth,strokeStyle:connectionColor},
+ endpointStyle:{fillStyle:'rgb(243,229,0)'},
+ endpoint: ["Dot", {
+ radius: 1
+ }],
+ alwaysRespectStubs:true,
+ anchors: [["Bottom"],["Top"]],
+ overlays:[]
+ };
+ return connectionObj;
+ },
+ _getAddNodeOverlay(context,sourceNode,target,transition){
+ var location=target.type==="placeholder"?1:0.5;
+ var transitionCount=sourceNode.transitions.length;
+ return {
+ id: sourceNode.id+"_"+target.id+"_"+"connector",
+ location:location,
+ /* jshint unused:vars */
+ create:function(component) {
+ var container=Ember.$('<div />');
+ var plus= Ember.$('<div class="fa fa-plus connector_overlay_new"></div>');
+ if ((sourceNode.isDecisionNode() && transitionCount>1 ||sourceNode.isForkNode() && transitionCount>2 ) &&
+ target.isPlaceholder() &&
+ !transition.isDefaultCasePath()){
+ var trash=Ember.$('<div class="node_actions node_left"><i class="fa fa-trash-o"></i></div>');
+ trash.on("click",function(){
+ context.deleteTransition(transition);
+ });
+ plus.append(trash);
+ }
+ container.append(plus);
+ return container;
+ },
+ events:{
+ click:function(labelOverlay, originalEvent) {
+ var element = originalEvent.target;
+ context.set('popOverElement', element);
+ context.setCurrentTransition(transition);
+ context.showWorkflowActionSelect(element);
+ }
+ }
+ };
+ },
+
+ _renderNodes(node,visitedNodes){
+ if (!node || node.isKillNode()){
+ return;
+ }
+ if (visitedNodes.contains(node)){
+ return;
+ }
+ visitedNodes.push(node);
+ if(!this.get("flattenedNodes").contains(node)){
+ this.get("flattenedNodes").pushObject(node);
+ }
+ if (node.transitions.length > 0){
+ node.transitions.forEach(function(transition) {
+ var target = transition.targetNode;
+ this._renderNodes(target,visitedNodes);
+ }.bind(this));
+ }
+ },
+ _connectNodes(context,sourceNode){
+ var connections=[];
+ var visitedNodes=[];
+ this._renderTransitions(sourceNode,connections,visitedNodes,context);
+ this._layout(connections);
+ this.designerPlumb.setSuspendDrawing(true);
+ this.designerPlumb.batch(function(){
+ connections.forEach(function(conn){
+ this.designerPlumb.connect(conn);
+ }.bind(this));
+ }.bind(this));
+ this.designerPlumb.setSuspendDrawing(false,true);
+
+ },
+ _renderTransitions(sourceNode,connections,visitedNodes,context){
+ var self=this;
+ if(!sourceNode){
+ return;
+ }
+ if (visitedNodes.contains(sourceNode)){
+ return;
+ }
+ if (sourceNode.hasTransition() ){
+ sourceNode.transitions.forEach(function(transition) {
+ var target = transition.targetNode;
+ if (target.isKillNode() || !Constants.showErrorTransitions && transition.isOnError()){
+ return;
+ }
+ var connectionObj=self._createConnection(sourceNode,target,transition);
+
+ if (transition.condition){
+ var conditionHTML = "<div class='decision-condition' title='"+transition.condition+"'>"+ transition.condition+"</div>";
+ connectionObj.overlays.push([ "Label", {label:conditionHTML, location:0.75, id:"myLabel" } ]);
+ }
+ if (!target.isPlaceholder()){
+ connectionObj.overlays.push(["PlainArrow",{location:-0.1,width: 7,length: 7}]);
+ }
+ if (!(sourceNode.isPlaceholder() || target.isKillNode())){
+ var addNodeoverlay=["Custom" , self._getAddNodeOverlay(context,sourceNode,target,transition)];
+ connectionObj.overlays.push(addNodeoverlay);
+ }
+ connections.push(connectionObj);
+ self._renderTransitions(target,connections,visitedNodes,context);
+ });
+ }
+ },
+ _layout(edges){
+ var nodes = Ember.$(".nodecontainer");
+ this.layoutManager.doLayout(this.get("context"),nodes,edges,this.get("workflow"));
+ },
+ initRenderer(callback,settings){
+ this.designerPlumb=jsPlumb.getInstance({});
+ this.layoutManager=LayoutManager.create({});
+ this.context=settings.context;
+ this.flattenedNodes=settings.flattenedNodes;
+ this.designerPlumb.ready(function() {
+ callback();
+ }.bind(this));
+ return this.designerPlumb;
+ },
+ refresh(){
+ this.designerPlumb.repaintEverything();
+ },
+ reset(){
+ if(!this.get('flattenedNodes')){
+ return;
+ }
+ this.get("flattenedNodes").clear();
+ this.designerPlumb.reset();
+ },
+ cleanup(){
+ if(!this.get('flattenedNodes')){
+ return;
+ }
+ this.get('flattenedNodes').clear();
+ this.designerPlumb.detachEveryConnection();
+ },
+ onDidUpdate(){
+ this._connectNodes(this.get("context"),this.get("workflow").startNode,this.get("workflow"));
+ },
+ renderWorkflow(workflow){
+ var visitedNodes=[];
+ this.set("workflow",workflow);
+ this._renderNodes(this.get("workflow").startNode,visitedNodes);
+ },
+
+ getBottomPosition(){
+ return {
+ top : this.get("context").$(".nodeEnd").offset().top,
+ left : this.get("context").$(".nodeEnd").offset().left
+ };
+ }
+
+});
+export {JSPlumbRenderer};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
index 7cb82e1..2962e71 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/mapping-utils.js
@@ -22,7 +22,6 @@ var MappingMixin= Ember.Mixin.create({
handleMapping(nodeDomain,nodeObj,mappings,nodeName){
var self=this;
mappings.forEach(function(mapping){
- var nodeVals=[];
if (mapping.mandatory){
if (!(nodeDomain[mapping.domain] || mapping.customHandler)){
var msgForVal=mapping.domain;
@@ -113,6 +112,7 @@ var MappingMixin= Ember.Mixin.create({
}
});
var ConfigurationMapper= Ember.Object.extend({
+ /* jshint unused:vars */
hanldeGeneration(node,nodeObj){
if (!node || !node.configuration || !node.configuration.property){
return;
@@ -205,24 +205,25 @@ var SLAMapper= Ember.Object.extend({
hanldeGeneration(sla,nodeObj){
if (sla){
var slaInfo=nodeObj["info"]={};
- slaInfo["__prefix"]="sla";
+ var slaPrefix="sla";
+ slaInfo["__prefix"]=slaPrefix;
if (sla.nominalTime){
- slaInfo["nominal-time"]=sla.nominalTime;
+ slaInfo[slaPrefix+":"+"nominal-time"]=sla.nominalTime;
}
if (sla.shouldStart){
- slaInfo["should-start"]="${"+sla.shouldStart.time+ "*"+sla.shouldStart.unit+"}";
+ slaInfo[slaPrefix+":"+"should-start"]="${"+sla.shouldStart.time+ "*"+sla.shouldStart.unit+"}";
}
if (sla.shouldEnd){
- slaInfo["should-end"]="${"+sla.shouldEnd.time+ "*"+sla.shouldEnd.unit+"}";
+ slaInfo[slaPrefix+":"+"should-end"]="${"+sla.shouldEnd.time+ "*"+sla.shouldEnd.unit+"}";
}
if (sla.maxDuration){
- slaInfo["max-duration"]="${"+sla.maxDuration.time+ "*"+sla.maxDuration.unit+"}";
+ slaInfo[slaPrefix+":"+"max-duration"]="${"+sla.maxDuration.time+ "*"+sla.maxDuration.unit+"}";
}
if (sla.alertEvents){
- slaInfo["alert-events"]=sla.alertEvents;
+ slaInfo[slaPrefix+":"+"alert-events"]=sla.alertEvents;
}
if (sla.alertContact){
- slaInfo["alert-contact"]=sla.alertContact;
+ slaInfo[slaPrefix+":"+"alert-contact"]=sla.alertContact;
}
}
@@ -230,18 +231,22 @@ var SLAMapper= Ember.Object.extend({
},
handleImport(domain,infoJson,key){
var sla=domain[key]=SlaInfo.create({});
- if (infoJson["nominal-time"]){
- sla.nominalTime=infoJson["nominal-time"];
+ if (infoJson["nominal-time"] && infoJson["nominal-time"].__text){
+ sla.nominalTime=infoJson["nominal-time"].__text;
+ }
+ if (infoJson["alert-contact"]&& infoJson["alert-contact"].__text){
+ sla.alertContact=infoJson["alert-contact"].__text;
+ }
+ if (infoJson["alert-events"] && infoJson["alert-events"].__text){
+ sla.alertEvents=infoJson["alert-events"].__text;
}
- sla.alertContact=infoJson["alert-contact"];
- sla.alertEvents=infoJson["alert-events"];
this.processTimePeriods(sla,infoJson,"should-start","shouldStart");
this.processTimePeriods(sla,infoJson,"should-end","shouldEnd");
this.processTimePeriods(sla,infoJson,"max-duration","maxDuration");
},
processTimePeriods(sla,infoJson,key,domainKey){
if (infoJson[key]){
- var timeParts=this.parseSlaTime(infoJson[key],key);
+ var timeParts=this.parseSlaTime(infoJson[key].__text,key);
sla[domainKey].time=timeParts[0];
sla[domainKey].unit=timeParts[1];
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-factory.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-factory.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-factory.js
index c440b8c..b6e2c73 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-factory.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-factory.js
@@ -21,10 +21,10 @@ import {Node} from '../domain/node';
import {idGen} from '../domain/id-gen';
var NodeFactory= Ember.Object.extend({
createStartNode(){
- return this.createNode({id:'node-start', type:'start',name:"Start"});
+ return this.createNode({id:this.generateNodeId(), type:'start',name:"Start"});
},
createEndNode(name){
- return this.createNode({id:'node-end', type:'end', name:name});
+ return this.createNode({id:this.generateNodeId(), type:'end', name:name});
},
createKillNode(name,message){
return this.createNode({id:this.generateNodeId(), type:"kill", name:name,killMessage:message});
@@ -108,6 +108,9 @@ var NodeFactory= Ember.Object.extend({
},
createNode(settings){
settings.factory=this;
+ if (!settings.id){
+ settings.id=this.generateNodeId();
+ }
return Node.create(settings);
},
generateNodeId(){
@@ -115,6 +118,9 @@ var NodeFactory= Ember.Object.extend({
},
generateName(){
return idGen.generateNodeName();
+ },
+ resetNodeIdTo(id){
+ return idGen.resetTo(id);
}
});
export{NodeFactory};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
index 49347d8..6bc305a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node-handler.js
@@ -17,49 +17,8 @@
import Ember from 'ember';
import {NodeFactory} from '../domain/node-factory';
-import * as actionJobHandler from '../domain/actionjob_hanlder';
-import {SlaInfo} from '../domain/sla-info';
import {SLAMapper} from "../domain/mapping-utils";
-var ActionTypeResolver=Ember.Object.extend({
- actionJobHandlerMap:null,
- validStandardActionProps:["ok","error","info"],
- init(){
- var settings={schemaVersions:this.schemaVersions};
- this.actionJobHandlerMap=new Map();
- this.actionJobHandlerMap.set("java",actionJobHandler.JavaActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("pig",actionJobHandler.PigActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("hive",actionJobHandler.HiveActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("hive2",actionJobHandler.Hive2ActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("sqoop",actionJobHandler.SqoopActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("shell",actionJobHandler.ShellActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("spark",actionJobHandler.SparkActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("map-reduce",actionJobHandler.MapRedActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("sub-workflow",actionJobHandler.SubWFActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("distcp",actionJobHandler.DistCpJobHandler.create(settings));
- this.actionJobHandlerMap.set("ssh",actionJobHandler.SshActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("email",actionJobHandler.EmailActionJobHandler.create(settings));
- this.actionJobHandlerMap.set("fs",actionJobHandler.FSActionJobHandler.create(settings));
- },
- getActionType(json){
- var self=this;
- var resolvedType=null;
- var problaleActionsTypes=[];
- Object.keys(json).forEach(function functionName(key) {
- if (!self.validStandardActionProps.contains(key) && !key.startsWith("_")){
- problaleActionsTypes.push(key);
- }
- });
- if (problaleActionsTypes.length===1){
- return problaleActionsTypes[0];
- }else{
- console.error("Invalid Action spec..",json);
- }
- return resolvedType;
- },
- getActionJobHandler(jobType){
- return this.actionJobHandlerMap.get(jobType);
- }
-});
+
var NodeHandler=Ember.Object.extend({
nodeFactory:NodeFactory.create({}),
context : {},
@@ -75,12 +34,14 @@ var NodeHandler=Ember.Object.extend({
handleNode(node){
return {"_name":node.get("name")};
},
-
+ /* jshint unused:vars */
handleTransitions(transitions,nodeObj){
},
+ /* jshint unused:vars */
handleImportNode(type,node){
},
+ /* jshint unused:vars */
handleImportTransitions(node,json,nodeMap){
}
});
@@ -248,4 +209,4 @@ var JoinNodeHandler= NodeHandler.extend({
node.addTransitionTo(nodeMap.get(json._to).node);
}
});
-export{ActionTypeResolver,NodeHandler,StartNodeHandler,EndNodeHandler,KillNodeHandler,ActionNodeHandler,DecisionNodeHandler,ForkNodeHandler,JoinNodeHandler};
+export{NodeHandler,StartNodeHandler,EndNodeHandler,KillNodeHandler,ActionNodeHandler,DecisionNodeHandler,ForkNodeHandler,JoinNodeHandler};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/node.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node.js
index c7ce003..cda7609 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/node.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/node.js
@@ -100,7 +100,7 @@ var Node = Ember.Object.extend(FindNodeMixin,{
}
},
addTransitionTo(target,condition){
- var transition = Transition.create({targetNode:target,sourceNode:this,condition:condition});
+ var transition = Transition.create({targetNode:target,sourceNodeId:this.id,condition:condition});
this.addTransition(transition);
return transition;
},
@@ -120,7 +120,6 @@ var Node = Ember.Object.extend(FindNodeMixin,{
},
removeTransition(transition){
- var transitions=this.get("transitions");
if (transition && this.transitions.indexOf(transition) > -1) {
this.transitions.splice(this.transitions.indexOf(transition), 1);
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/sla-info.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/sla-info.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/sla-info.js
index 76dffbd..9d90280 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/sla-info.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/sla-info.js
@@ -17,43 +17,43 @@
import Ember from 'ember';
var SlaInfo = Ember.Object.extend(Ember.Copyable,{
copy (){
- var slaInfo = {}
+ var slaInfo = {};
for (let key in this) {
slaInfo[key] = Ember.copy(this[key]) ;
}
return slaInfo;
},
init (){
- this.nominalTime='';
+ this.nominalTime=undefined;
this.shouldStart = {
- time : '',
- unit : ''
+ time : undefined,
+ unit : undefined
};
this.shouldEnd = {
- time : '',
- unit : ''
+ time : undefined,
+ unit : undefined
};
this.maxDuration = {
- time : '',
- unit : ''
+ time : undefined,
+ unit : undefined
};
- this.alertEvents = '';
- this.alertContacts = '';
+ this.alertEvents = undefined;
+ this.alertContacts = undefined;
},
- nominalTime:'',
+ nominalTime:undefined,
shouldStart : {
- time : '',
- unit : ''
+ time : undefined,
+ unit : undefined
},
shouldEnd : {
- time : '',
- unit : ''
+ time : undefined,
+ unit : undefined
},
maxDuration : {
- time : '',
- unit : ''
+ time : undefined,
+ unit : undefined
},
- alertEvents : '',
- alertContacts : ''
+ alertEvents : undefined,
+ alertContacts : undefined
});
export {SlaInfo};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/transition.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/transition.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/transition.js
index 70d7a81..b14484e 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/transition.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/transition.js
@@ -18,7 +18,6 @@
import Ember from 'ember';
var Transition = Ember.Object.extend({
id:null,
- sourceNode:null,
targetNode:null,
type:null,
condition:null,
@@ -35,9 +34,7 @@ var Transition = Ember.Object.extend({
isDefaultCasePath(){
return this.condition==="default";
},
- getSourceNode(){
- return this.get("sourceNode");
- },
+
getTargetNode(skipPlaceholder){
var currNode=this.targetNode;
if (skipPlaceholder===false){
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
index f29adb6..7415544 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-importer.js
@@ -95,7 +95,7 @@ var WorkflowImporter= Ember.Object.extend({
},
getNodeIds(nodeMap){
var ids=[];
- nodeMap.forEach(function(entry,key){
+ nodeMap.forEach(function(entry){
var node=entry.node;
ids.push(node.id);
});
@@ -103,7 +103,7 @@ var WorkflowImporter= Ember.Object.extend({
},
getNodeNames(nodeMap){
var names=[];
- nodeMap.forEach(function(entry,key){
+ nodeMap.forEach(function(entry){
var node=entry.node;
names.push(node.id);
});
@@ -113,7 +113,7 @@ var WorkflowImporter= Ember.Object.extend({
if (this.containsKillNode(nodeMap)){
workflow.resetKillNodes();
}
- nodeMap.forEach(function(entry,key){
+ nodeMap.forEach(function(entry){
var node=entry.node;
if (node.isKillNode()){
workflow.get("killNodes").pushObject(node);
@@ -122,7 +122,7 @@ var WorkflowImporter= Ember.Object.extend({
},
containsKillNode(nodeMap){
var containsKillNode=false;
- nodeMap.forEach(function(entry,key){
+ nodeMap.forEach(function(entry){
var node=entry.node;
if (node.isKillNode()){
containsKillNode=true;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
new file mode 100644
index 0000000..fa428bb
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-json-importer.js
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import Ember from 'ember';
+import {Workflow} from '../domain/workflow';
+import {NodeFactory} from '../domain/node-factory';
+var WorkflowJsonImporter= Ember.Object.extend({
+ nodeFactory:NodeFactory.create({}),
+ importWorkflow(workflowJsonStr){
+ if (!workflowJsonStr){
+ return null;
+ }
+ try{
+ var workflowJson=JSON.parse(workflowJsonStr);
+ var workflow=Workflow.create({});
+ workflow.initialize();
+ workflow.set("name",workflowJson.name);
+ this.restoreKillNodes(workflowJson.killNodes,workflow);
+ var nodeMap= new Map();
+ var startNode=this.visitNode(workflowJson.startNode,nodeMap);
+ workflow.set("startNode",startNode);
+ var maxId=0;
+ for(let value of nodeMap.keys()){
+ console.log("Value in it=",value);
+ var id=Number.parseInt(value.substr(5));
+ if (id>maxId){
+ maxId=id;
+ }
+ }
+ this.nodeFactory.resetNodeIdTo(maxId+1);
+ console.log("imported workflow==",workflow);
+ return workflow;
+ }catch(e){
+ console.error(e);
+ return null;
+ }
+ },
+ visitNode(nodeJson,nodeMap){
+ var self=this;
+ if (!nodeJson){
+ return;
+ }
+ var node;
+ if (!nodeMap.has(nodeJson.id)){
+ node=this.nodeFactory.createNode({id:nodeJson.id, type:nodeJson.type,name:nodeJson.name,actionType:nodeJson.actionType,killMessage:nodeJson.killMessage});
+ node.set("domain",nodeJson.domain);
+ node.set("errorMsgs",nodeJson.errorMsgs);
+ node.set("errors",nodeJson.errors);
+ nodeMap.set(node.id,node);
+ if (nodeJson.transitions){
+ nodeJson.transitions.forEach(function(nodeTran){
+ var transitions=nodeTran;
+ if (!Ember.isArray(nodeTran)){
+ transitions=[nodeTran];
+ }
+ transitions.forEach(function(tran){
+ var targetNodeJson=tran.targetNode;
+ var targetNode=self.visitNode(targetNodeJson,nodeMap);
+ node.addTransitionTo(targetNode,tran.condition);
+ });
+ });
+ }
+ }else{
+ node=nodeMap.get(nodeJson.id);
+ }
+ return node;
+ },
+ restoreKillNodes(killnodesJson,workflow){
+ if (!killnodesJson){
+ return;
+ }
+ workflow.resetKillNodes();
+ killnodesJson.forEach(function(killNodeJson){
+ workflow.createKillNode(killNodeJson.name,killNodeJson.killMessage);
+ });
+ console.log("killnodes json=",killnodesJson);
+ }
+});
+export {WorkflowJsonImporter};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-path-util.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-path-util.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-path-util.js
new file mode 100644
index 0000000..c921455
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-path-util.js
@@ -0,0 +1,73 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+export default Ember.Object.create({
+ findPath(source, target){
+ var visitedNodes = [];
+ var currentPath = [];
+ var allPaths = [];
+ this._findPath(source, target, visitedNodes, currentPath, 0, allPaths);
+ return allPaths;
+ },
+ _findPath(source, target, visitedNodes, currentPath, pathIndex, allPaths){
+ visitedNodes.pushObject(source);
+ currentPath[pathIndex++] = source;
+ if(source.id === target.id){
+ if(!allPaths[allPaths.length]){
+ var index = currentPath.indexOf(target);
+ allPaths[allPaths.length] = currentPath.slice(0, index+1);
+ }
+ }
+ if(source.hasTransition()){
+ source.transitions.forEach((transition)=>{
+ var node = transition.targetNode;
+ if(node.hasTransition() && !visitedNodes.findBy('id', node.id)){
+ this._findPath(node, target, visitedNodes, currentPath, pathIndex, allPaths);
+ }
+ }, this);
+ }
+ pathIndex--;
+ visitedNodes.removeObject(source);
+ },
+ _getAllNodes(workflow){
+ var workflowNodes = [];
+ workflow.nodeVisitor.process(workflow.startNode, (node) =>{
+ workflowNodes.pushObject(node);
+ });
+ return workflowNodes;
+ },
+ findValidTransitionsTo(workflow, node){
+ var validTransitionsTo = [];
+ if(!node.hasTransition()){
+ return validTransitionsTo;
+ }
+ var paths = this.findPath(workflow.get('startNode'), node);
+ var workflowNodes = this._getAllNodes(workflow);
+ validTransitionsTo = workflowNodes.slice();
+ workflowNodes.forEach((node)=>{
+ paths.forEach((path)=>{
+ if(path.contains(node)){
+ validTransitionsTo.removeObject(node);
+ }
+ }, this);
+ }, this);
+ validTransitionsTo = validTransitionsTo.reject((node)=>{
+ return node.get('type') === 'placeholder';
+ }, this);
+ return validTransitionsTo;
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
index 9fc791c..7049fde 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow-xml-generator.js
@@ -18,7 +18,6 @@
import Ember from 'ember';
import {WorkflowXmlMapper} from '../domain/workflow_xml_mapper';
import {NodeVisitor} from '../domain/node-visitor';
-import Constants from '../utils/constants';
var WorkflowGenerator= Ember.Object.extend({
workflowMapper:null,
x2js : new X2JS({useDoubleQuotes:true}),
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
index 5908de5..f4fc20d 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow.js
@@ -21,8 +21,7 @@ import {FindNodeMixin} from '../domain/findnode-mixin';
import {NodeFactory} from '../domain/node-factory';
import SchemaVersions from '../domain/schema-versions';
import {NodeVisitor} from '../domain/node-visitor';
-import {idGen} from '../domain/id-gen';
-import {SlaInfo} from '../domain/sla-info'
+import {SlaInfo} from '../domain/sla-info';
var Workflow= Ember.Object.extend(FindNodeMixin,{
name:"",
startNode:null,
@@ -60,52 +59,13 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
//TODO idGen.reset();
this.initialize();
},
- findCommonTargetNodeId(node){
- var nodeIds = {}, targ, decPath = node.getTargets(), tempId = 0;
- for(var i =0; i< decPath.length; i++){
- var currNode = decPath[i];
- do {
- if(nodeIds.hasOwnProperty(currNode.get("id"))){
- nodeIds[currNode.get("id")] = nodeIds[currNode.get("id")] + 1;
- } else {
- nodeIds[currNode.get("id")] = 1;
- }
- if(currNode.get("id") === "node-end"){
- break;
- }
- currNode = currNode.getTargets()[0];
- } while(currNode && currNode.get("id"));
- }
- for(var j in nodeIds){
- if(tempId < nodeIds[j]){
- targ = j;
- tempId = nodeIds[j];
- }
- }
- return targ;
- },
+
findJoinNode(node){
- var commonTargetId=null;
- var commonTarget=null;
- if (node.isDecisionNode()){
- if (Constants.globalSetting.useJoinNodeForDecision){
- var target=this.findNodeById(node,"decision_end_"+node.get("id"));
- if (!target){
- commonTargetId=this.findCommonTargetNodeId(node);
- commonTarget=this.findNodeById(this.startNode,commonTargetId);
- return commonTarget;
- }else{
- return target;
- }
- }else{
- commonTargetId=this.findCommonTargetNodeId(node);
- commonTarget=this.findNodeById(this.startNode,commonTargetId);
- return commonTarget;
- }
+ if (node.isDecisionNode() || node.isForkNode()){
+ return this.findCommonTargetNode(this.startNode,node);
}else if (node.isForkNode()) {
- commonTargetId=this.findCommonTargetNodeId(node);
- commonTarget=this.findNodeById(this.startNode,commonTargetId);
- return commonTarget;
+ //TODO find join node by id if it is efficient later..
+ return this.findCommonTargetNode(this.startNode,node);
}else{
return null;
}
@@ -136,7 +96,7 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
}else{
}
},
- generatedNode(target,type){
+ generatedNode(target,type,settings){
var generatedNode=null;
if ("decision" === type){
generatedNode=this.nodeFactory.generateDecisionNode(target);
@@ -144,32 +104,38 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
generatedNode=this.nodeFactory.generateForkNode(target);
}else if ("kill" === type){
generatedNode = this.nodeFactory.createKillNode(settings.name);
- source.deleteCurrentKillNode();
+ //source.deleteCurrentKillNode();//TODO how to get source...
}else{
generatedNode = this.nodeFactory.createActionNode(type);
generatedNode.addTransitionTo(target);
}
return generatedNode;
},
- addKillNode(node,settings){
- var generatedNode=this.generatedNode(null,"kill");
+
+ addKillNode(source,settings){
+ var generatedNode=this.generatedNode(null,"kill",settings);
return source.addTransitionTo(generatedNode,"error");
},
addNode(transition,type,settings) {
- var source=transition.sourceNode;
var target=transition.targetNode;
var computedTarget=target;
if (target && target.isPlaceholder()){
computedTarget=target.getTargets()[0];
}
- var generatedNode=this.generatedNode(computedTarget,type);
- transition.targetNode=generatedNode;
+ var generatedNode=this.generatedNode(computedTarget,type,settings);
+ var sourceNode=this.findNodeById(this.startNode,transition.sourceNodeId);
+ if (sourceNode.isPlaceholder()){
+ var orignalTransition=this.findTransitionTo(this.startNode,sourceNode.id);
+ orignalTransition.targetNode=generatedNode;
+ }else{
+ transition.targetNode=generatedNode;
+ }
return generatedNode;
},
deleteKillNode(node){
let killNodes = this.get("killNodes");
var killNodeReferenced=false;
- this.nodeVisitor.process(this.startNode,function(n,ctx){
+ this.nodeVisitor.process(this.startNode,function(n){
if (n.errorNode && n.errorNode.name===node.name){
killNodeReferenced=true;
}
@@ -195,35 +161,37 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
var target=node.getDefaultTransitionTarget();
if (node.isForkNode()|| node.isDecisionNode()){
target=this.findJoinNode(node);
+ if (!target){//A bug will give target as null if the decision has single path.
+ target=node.getDefaultTransitionTarget();
+ }
if (target.isJoinNode()){
target=target.getDefaultTransitionTarget();
}
}
var transitionslist=this.findTransistionsToNode(node);
transitionslist.forEach(function(tran){
- if (tran.getSourceNode().isDecisionNode()){
- var joinNode=self.findJoinNode(tran.getSourceNode());
+ var sourceNode=self.findNodeById(self.startNode,tran.sourceNodeId);
+ var joinNode;
+ if (sourceNode.isDecisionNode()){
+ joinNode=self.findJoinNode(sourceNode);
if (joinNode===target){
if (tran.isDefaultCasePath()){
- var placeholderNode=self.nodeFactory.createPlaceholderNode(target);
- tran.targetNode=placeholderNode;
- }else if (tran.getSourceNode().getOkTransitionCount()>2){
- tran.getSourceNode().removeTransition(tran);
+ tran.targetNode=self.nodeFactory.createPlaceholderNode(target);
+ }else if (sourceNode.getOkTransitionCount()>2){
+ sourceNode.removeTransition(tran);
}else{
- var placeholderNode=self.nodeFactory.createPlaceholderNode(target);
- tran.targetNode=placeholderNode;
+ tran.targetNode=self.nodeFactory.createPlaceholderNode(target);
}
}else{
tran.targetNode=target;
}
- }else if (tran.getSourceNode().isForkNode()){
- var joinNode=self.findJoinNode(tran.getSourceNode());
+ }else if (sourceNode.isForkNode()){
+ joinNode=self.findJoinNode(sourceNode);
if (joinNode===target){
- if (tran.getSourceNode().getOkTransitionCount()>2){
- tran.getSourceNode().removeTransition(tran);
+ if (sourceNode.getOkTransitionCount()>2){
+ sourceNode.removeTransition(tran);
}else{
- var placeholderNode=self.nodeFactory.createPlaceholderNode(target);
- tran.targetNode=placeholderNode;
+ tran.targetNode=self.nodeFactory.createPlaceholderNode(target);
}
}else{
tran.targetNode=target;
@@ -234,13 +202,15 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
});
},
deleteTransition(transition){
- var src=transition.getSourceNode();
+ var src=this.findNodeById(this.startNode,transition.sourceNodeId);
src.removeTransition(transition);
},
deleteEmptyTransitions(transitionslist){
+ var self=this;
transitionslist.forEach(function(tran){
- if (tran.getSourceNode().isForkNode()&& tran.getTargetNode().isJoinNode()){
- tran.getSourceNode().removeTransition(tran);
+ var sourceNode=this.findNodeById(self.startNode,tran.sourceNodeId);
+ if (sourceNode.isForkNode()&& tran.getTargetNode().isJoinNode()){
+ sourceNode.removeTransition(tran);
}
});
},
@@ -261,6 +231,4 @@ var Workflow= Ember.Object.extend(FindNodeMixin,{
}
}
});
-
-
export {Workflow};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow_xml_mapper.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow_xml_mapper.js b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow_xml_mapper.js
index d5dc4da..70581bf 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow_xml_mapper.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/domain/workflow_xml_mapper.js
@@ -18,6 +18,7 @@
import Ember from 'ember';
import * as nodeHandler from '../domain/node-handler';
import {SLAMapper} from "../domain/mapping-utils";
+import {ActionTypeResolver} from "../domain/action-type-resolver";
import {MappingMixin,ConfigurationMapper} from "../domain/mapping-utils";
var WorkflowXmlMapper= Ember.Object.extend({
@@ -27,7 +28,7 @@ var WorkflowXmlMapper= Ember.Object.extend({
slaMapper: SLAMapper.create({}),
schemaVersions:null,
init: function() {
- this.actionTypeResolver=nodeHandler.ActionTypeResolver.create({schemaVersions:this.schemaVersions});
+ this.actionTypeResolver=ActionTypeResolver.create({schemaVersions:this.schemaVersions});
this.set("globalConfigHandler",GlobalConfigHandler.create({}));
this.set("slaMapper",SLAMapper.create({}));
this.nodeHandlerMap=new Map();
@@ -106,7 +107,7 @@ var WorkflowXmlMapper= Ember.Object.extend({
if (!parameters|| !parameters.property){
return;
}
- workflow.parameters={"configuration":{property:[]}}
+ workflow.parameters={"configuration":{property:[]}};
parameters.property.forEach(function(prop){
workflow.parameters.configuration.property.push({"name":prop.name,"value":prop.value});
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/helpers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/helpers/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/app/helpers/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/index.html
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/index.html b/contrib/views/wfmanager/src/main/resources/ui/app/index.html
index a317a48..df243ad 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/index.html
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/index.html
@@ -33,6 +33,15 @@
</head>
<body>
+
+<div style="display:none;">
+<!-- preloading images for designer-->
+ <img src="assets/play.png"/>
+ <img src="assets/stop.png"/>
+ <img src="assets/join.png"/>
+ <img src="assets/sitemap.png"/>
+</div>
+
{{content-for "body"}}
<script src="assets/vendor.js"></script>
<script src="assets/oozie-designer.js"></script>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/routes/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/app/routes/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
index d0ef5e0..949d39a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/dashboard.js
@@ -62,11 +62,19 @@ export default Ember.Route.extend({
});
return deferred.promise;
},
+ setPageResultLen(){
+ /*
+ setting the no of jobs to be displayed to multiple of 5
+ */
+ var relHeight = parseInt(Ember.$(window).width()/100);
+ return relHeight - relHeight%5;
+ },
search(params){
params = params || {};
var type = params.type || "wf",
start = Number(params.start || 1),
- len = Number(params.len || Ember.ENV.PAGE_SIZE),
+ //len = Number(params.len || Ember.ENV.PAGE_SIZE),
+ len = this.setPageResultLen(),
index = 0,
filter = params.filter || "",
API_URL = Ember.ENV.API_URL,
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
index cec0e9e..5ed2619 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/routes/design.js
@@ -1,25 +1,27 @@
/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
import Ember from 'ember';
export default Ember.Route.extend({
-xmlAppPath : null,
-beforeModel: function(transition){
- this.set("xmlAppPath", transition.queryParams.appPath);
+
+ beforeModel: function(transition){
+ this.set("xmlAppPath", transition.queryParams.appPath);
+ this.controllerFor('design').set("xmlAppPath", transition.queryParams.appPath);
}
+
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/services/workflow-clipboard.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/services/workflow-clipboard.js b/contrib/views/wfmanager/src/main/resources/ui/app/services/workflow-clipboard.js
new file mode 100644
index 0000000..8784cda
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/services/workflow-clipboard.js
@@ -0,0 +1,34 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+ clipboard : null,
+ setContent(node, operation){
+ var clipboardContent = {
+ name : node.name,
+ domain : Ember.copy(node.domain),
+ type : node.type,
+ actionType : node.actionType,
+ operation : operation
+ };
+ this.set('clipboard', clipboardContent);
+ },
+ getContent (){
+ return this.get('clipboard');
+ }
+});
[05/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/services/workspace-manager.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/services/workspace-manager.js b/contrib/views/wfmanager/src/main/resources/ui/app/services/workspace-manager.js
new file mode 100644
index 0000000..f5eb6e7
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/services/workspace-manager.js
@@ -0,0 +1,62 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Service.extend({
+ tabsInfo : {},
+ workInProgress : {},
+ setLastActiveTab(tabId){
+ console.log("setting last active tabId "+tabId);
+ localStorage.setItem('lastActiveTab', tabId);
+ },
+ getLastActiveTab(){
+ console.log("get last active "+localStorage.getItem('lastActiveTab'));
+ return localStorage.getItem('lastActiveTab');
+ },
+ restoreTabs(){
+ var tabs = localStorage.getItem('tabsInfo');
+ console.log("Restoring tabs "+tabs);
+ return JSON.parse(tabs);
+ },
+ saveTabs(tabs){
+ if(!tabs){
+ return;
+ }
+ var tabArray = [];
+ tabs.forEach((tab)=>{
+ tabArray.push({
+ type : tab.type,
+ id : tab.id,
+ name : tab.name
+ });
+ });
+ console.log("Saving tabs "+JSON.stringify(tabArray));
+ localStorage.setItem('tabsInfo', JSON.stringify(tabArray));
+ },
+ restoreWorkInProgress(id){
+ console.log("Restoring workInProgress "+id);
+ return localStorage.getItem(id);
+ },
+ saveWorkInProgress(id, workInProgress){
+ console.log("Restoring workInProgress "+id);
+ localStorage.setItem(id, workInProgress);
+ },
+ deleteWorkInProgress(id){
+ localStorage.removeItem(id);
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
new file mode 100644
index 0000000..5d1b3a3
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/styles/app.less
@@ -0,0 +1,1497 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@bgColor: #eee;
+@bgGreenActive: #5bb75b;
+@moduleHeaderBgColor: #fafafa;
+@nodeDefaultHeight: 40px;
+@nodeDefaultWidth: 40px;
+@defaultRed: red;
+@defaultBorderRadius: 5px;
+@nodeActionBgColor: #E5E5E5;
+@defaultPropertiesEditorHeight: 350px;
+
+body {
+ background: @bgColor;
+ padding: 0;
+ margin: 0;
+}
+a {
+ color: #000;
+}
+.padding0 {
+ padding: 0px;
+}
+.paddingtop7{
+ padding-top:7px;
+}
+.paddingtop8{
+ padding-top:7px;
+}
+.paddingbottom8{
+ padding-bottom:7px;
+}
+.paddingtop10{
+ padding-top:10px;
+}
+.padding10{
+ margin-top: 10px;
+}
+.padding20{
+ margin-top: 20px;
+}
+.marginleft20{
+ margin-left: 20px !important;
+}
+.paddingright10{
+ padding-right: 10px;
+}
+.marginright5{
+ margin-right: 5px !important;
+}
+#arrow{
+ top: 24%;
+ left: -22px;
+ margin-top: -11px;
+ border-right-color: #999 !important;
+ border-right-color: rgba(0, 0, 0, .25);
+ border-left-width: 0;
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 11px;
+}
+
+.container-custom {
+ background-color: @moduleHeaderBgColor;
+}
+
+.disabled {
+ cursor:none;
+}
+#header {
+ white-space: nowrap;
+ background: @bgGreenActive;
+ background-position: 10px;
+ color: yellow;
+ height: 50px;
+ padding: 10px;
+ font-size: 20px;
+}
+.branch{
+ padding: 0px !important;
+ border: 0px !important;
+ background: inherit !important;
+}
+
+.branch input {
+ border: 0px;
+ text-align: center;
+}
+
+#designer {
+ position: relative;
+}
+
+#wf_title {
+ border-bottom: 1px dotted #000;
+}
+
+.editable {
+ padding: 5px 10px;
+ border: 1px solid transparent;
+ background: transparent;
+ white-space: nowrap;
+ text-align: left;
+ margin: 0 2px;
+}
+
+.editable:focus,
+.editable:hover {
+ border: 1px solid #999;
+ background: #fff;
+ cursor: text;
+}
+
+.action {
+ float: left;
+ padding: 5px;
+ margin: 2px;
+ height: 60px;
+ line-height: 50px;
+ width: 62px;
+ font-size: small;
+ overflow: hidden;
+ text-align: center;
+}
+
+.node,
+.actions_list_left li:hover {
+ /* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ffffff+0,e5e5e5+100;White+3D */
+ background: #ffffff;
+}
+
+.node {
+ text-align: center;
+ position: absolute;
+ left: 50%;
+ border: 1px solid #bbb;
+ overflow: visible;
+ background: transparent;
+ border: none;
+}
+
+.node-item{
+ background:#e5e5e5;
+ border: 1px solid #ABABAB;
+ z-index:4;
+
+}
+
+.action_node {
+ min-width: 195px;
+}
+
+.fork,
+.join {
+ border-radius: 70px;
+ width: @nodeDefaultWidth;
+ height: @nodeDefaultHeight;
+ white-space: wrap;
+ padding-top: 10px;
+}
+
+.start,
+.end {
+ border-radius: 60px;
+ width: @nodeDefaultWidth;
+ height: @nodeDefaultHeight;
+ background: #fff;
+ line-height: 25px;
+ cursor: not-allowed;
+}
+
+.start {
+ top: 20px;
+ padding-left: 7px;
+ padding-top: 6px;
+}
+.kill{
+ border-radius: @defaultBorderRadius;
+ min-width: 178px;
+ height: @nodeDefaultHeight;
+}
+.kill .fa-ban {
+ color: @defaultRed;
+}
+.hrClass{
+ margin-bottom: 10px;
+ margin-top: 10px;
+}
+
+.kill-name{
+ padding-left: 40px;
+ margin-top: -35px;
+}
+
+.node .editable {
+ padding: 2px 5px;
+ width: 8em;
+ text-align: center;
+}
+
+.node .error{
+ border: 1px solid #a94442;
+}
+
+.connector_overlay {
+ transition: all .3s ease-in;
+ white-space: nowrap;
+ opacity: .8;
+ border: 1px solid #ddd;
+ background: #1a8cff;
+ border-radius: 30px;
+ width: 30px;
+ height: 30px;
+ line-height: 28px;
+ text-align: center;
+ cursor: pointer;
+ transform: scale(0.8);
+
+}
+
+.jsplumb-hover .connector_overlay,
+.connector_overlay:hover {
+ opacity: 1;
+}
+
+.node_actions {
+ transition: opacity 1s ease-in;
+ opacity: 0;
+ position: absolute;
+ white-space: nowrap;
+ border: 1px solid #999;
+ background: @nodeActionBgColor;
+ border-radius: 3px;
+ min-width: 20px;
+ height: 28px;
+ cursor: pointer;
+}
+.node_actions i{
+ padding: 5px;
+}
+.node_properties {
+ border-radius: 30px;
+ cursor: pointer;
+}
+.node_properties:hover {
+ cursor: pointer;
+}
+.decision_node .node_properties {
+ margin-top: -16px;
+}
+.decisionNodeError{
+ position: relative;
+ left: 50px;
+ }
+.action-node {
+ border-radius: @defaultBorderRadius;
+ height: 38px;
+}
+.node_left .fa-trash-o{
+ color: @defaultRed;
+}
+.node_left {
+ right: -45px;
+ top: -61%;
+}
+.decision_node .node_left{
+ transform: rotate(315deg) scale(1.4);
+ right: -50px;
+ top: -126%;
+}
+.nodeEnd{
+ top:15%;
+ position: relative;
+}
+.nodeStart{
+ right:5%;
+ position: relative;
+}
+.node_bottom {
+ bottom: 50%;
+ left: 50%;
+ z-index: 5;
+ transform: translate(-50%, -20%) scale(0.8);
+ opacity: 1;
+ border-radius: 3px;
+ width: 40px;
+ height: 24px;
+}
+.fork .node_bottom {
+ top: 80%;
+}
+.node_bottom_actions{
+ position: absolute;
+ background: @nodeActionBgColor;
+ white-space: nowrap;
+}
+.node:hover .node_actions {
+ opacity: 1;
+}
+
+.action_node {
+ border-radius: 4px;
+}
+
+input:invalid {
+ border: 1px solid @defaultRed;
+}
+
+.fa-exclamation-triangle {
+ color: @defaultRed;
+}
+
+.actions_list_left {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.actions_list_left li.disabled {
+ cursor: not-allowed;
+ background: #eee;
+ color: #ccc;
+}
+
+.actions_list_left li {
+ background: #fff;
+ width: 60px;
+ padding: 10px;
+ border: 1px solid silver;
+ border-radius: @defaultBorderRadius;
+ margin: 2px 0;
+ cursor: move;
+ z-index: 1000;
+ display: inline-block;
+ position: relative;
+ text-align: center;
+}
+
+.control_flow_node,
+.control_flow li:hover {
+ /* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#fdfeea+0,e8f135+100 */
+ /*background: #fdfeea;*/
+ /* Old browsers */
+ /*background: -moz-linear-gradient(top, #fdfeea 0%, #e8f135 100%);*/
+ /* FF3.6-15 */
+ /*background: -webkit-linear-gradient(top, #fdfeea 0%, #e8f135 100%);*/
+ /* Chrome10-25,Safari5.1-6 */
+ /*background: linear-gradient(to bottom, #fdfeea 0%, #e8f135 100%);*/
+ /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
+ /*filter: progid: DXImageTransform.Microsoft.gradient( startColorstr='#fdfeea', endColorstr='#e8f135', GradientType=0);*/
+ /* IE6-9 */
+}
+.decision-condition {
+ white-space: nowrap;
+ width: 10em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ border: 1px solid #D0D0D0;
+ border-radius: 3px;
+ background-color: #F5F5F5;
+ padding: 3px;
+ font-size: 11px;
+ opacity: 0.8;
+}
+.decision_node {
+ transform: rotate(45deg) scale(.7);
+ width: 60px;
+ height: 60px;
+ padding: 5px;
+ float: right;
+ margin: 0 2px;
+}
+.decision-data-wrapper{
+ transform: rotate(-45deg) scale(1.3); ;
+}
+.decision_node_data .editable{
+ margin-right: 10px;
+}
+.decision_node_data {
+ padding-right: 31px;
+ float: right;
+ margin: 0 2px;
+}
+.fork_node_data {
+ float: right;
+ margin-top: -15px;
+}
+.fork_node_data .editable {
+ margin-right: 5px;
+}
+.decision_node .content {
+ text-align: center;
+ position: absolute;
+ padding: 0 5px;
+ width: 120px;
+ height: 70px;
+ transform: rotate(-45deg) scale(1.2) translate(-13%, 30%);
+ white-space: nowrap;
+}
+
+.breadcrumb {
+ margin: 0;
+}
+
+.collapse.width {
+ height: auto;
+ -webkit-transition: width 0.35s ease;
+ -moz-transition: width 0.35s ease;
+ -o-transition: width 0.35s ease;
+ transition: width 0.35s ease;
+}
+
+.highlighter-always {
+ opacity: 1;
+ animation-name: highlighter;
+ animation-duration: 1s;
+ animation-iteration-count: infinite;
+ animation-timing-function: ease-out;
+}
+
+@keyframes highlighter {
+ 0% {
+ transform: scale(1)
+ }
+ 50% {
+ transform: scale(1.5)
+ }
+ 100% {
+ transform: scale(1)
+ }
+}
+
+.control_flow li._fork {
+ margin: 4px 8px;
+}
+
+.control_flow li.switch {
+ border-radius: 0px;
+ transform: rotate(45deg) translate(0%, -0%) scale(.9);
+}
+
+.action_node_data {
+ padding: 5px;
+ float: left;
+ margin: 0 2px;
+}
+
+#content {
+ padding: 0;
+ margin: 0;
+ float: left;
+ position: relative;
+ transition: left .6s cubic-bezier(0.175, 0.885, 0.320, 1.275);
+}
+
+.expanded {
+ left: 0px;
+}
+
+.expanded:after {
+ content: "\f100" !important;
+}
+
+.collapsed {
+ left: -215px;
+}
+
+.title-btn,
+.title-btn:hover {
+ border: 0;
+ background: transparent;
+}
+
+.back_button {
+ height: 30px;
+ background-color: #fff;
+ position: relative;
+ margin-left: 13px;
+ border-radius: @defaultBorderRadius;
+ border: 1px solid #ccc;
+}
+
+.back_button:before {
+ content: "";
+ position: absolute;
+ top: -1px;
+ left: -13px;
+ border-style: solid;
+ border-width: 15px 15px 15px 0;
+ border-color: transparent #ccc transparent transparent;
+}
+
+.back_button:after {
+ content: "";
+ position: absolute;
+ top: 0px;
+ left: -12px;
+ border-style: solid;
+ border-width: 14px 14px 14px 0;
+ border-color: transparent #fff transparent transparent;
+}
+
+.back_button > a {
+ display: block;
+ text-decoration: none;
+ text-align: center;
+ color: #000;
+ padding: 0 10px 0 5px;
+ line-height: 27px;
+ font-size: smaller;
+}
+
+.ambari-view #header {
+ display: none;
+}
+
+.ambari-view #content {
+ padding: 0;
+}
+
+.ambari-view body {
+ background: #fff;
+}
+
+.messageDiv {
+ position: absolute;
+ left: 40%;
+ top: 100px;
+ z-index: 1;
+}
+
+.workflow-error {
+ top:50px;
+ left: 75%;
+ z-index: 1;
+}
+
+#action_properties_dialog .modal-body {
+ max-height: @defaultPropertiesEditorHeight;
+ overflow-y: scroll;
+ overflow-x: hidden;
+}
+
+#action_properties_dialog .container,
+#global_properties_dialog .container {
+ max-width: 180%;
+}
+
+#action_properties_dialog .blank-form {
+ right: 15px;
+ position: relative;
+}
+
+#action_properties_dialog .modal-dialog,
+#workflow_sla_dialog .modal-dialog,
+#global_properties_dialog .modal-dialog,
+#workflow_parameters_dialog .modal-dialog,
+#workflow_credentials_dialog .modal-dialog,
+#version-settings-dialog .modal-dialog,
+#control-dialog .modal-dialog,
+#ConfirmDialog .modal-dialog,
+#killnode-manager-dialog .modal-dialog {
+ width: 800px;
+}
+#configureJob .modal-dialog{
+ width: 650px;
+}
+#collapseOne{
+ margin: 10px;
+}
+.panel-heading {
+ padding: 4px 15px;
+}
+
+#action_properties_dialog .panel-default > .panel-heading,
+#global_properties_dialog .panel-default > .panel-heading,
+#workflow_sla_dialog .panel-default > .panel-heading,
+#workflow_credentials_dialog .panel-default > .panel-heading,
+#configureWorkfowModal .panel-default > .panel-heading,
+#workflow_parameters_dialog .panel-default > .panel-heading,
+#killnode-manager-dialog .panel-default > .panel-heading,
+ .whiteLabel, .whiteLabel:hover, .whiteLabel:focus, .whiteLabel:visited, .whiteLabel:active {
+ background-color: @bgGreenActive;
+ color: #fff;
+}
+.btn-primary{
+ background-color: @bgGreenActive !important;
+ border-color: #289028 !important;
+ color: #fff;
+}
+.btn-primary:visited,.btn-primary:focus,.btn-primary:active,.btn-primary.active{
+ background-color: @bgGreenActive !important;
+ border-color: #289028 !important;
+ color: #fff;
+}
+.btn-primary:hover{
+ background-color: #289028 !important;
+ border-color: #289028 !important;
+ color: #fff;
+}
+._actions_popup {
+ padding: 4px;
+}
+
+._actions_popup .control_flow {
+ padding-left: 20%;
+}
+
+._actions_popup ul {
+ padding: 0;
+ margin: 0;
+}
+
+._actions_popup h4 {
+ font-size: 10px;
+ font-weight: bold;
+ border-bottom: 1px solid #e5e5e5;
+ padding-bottom: 5px;
+}
+
+._actions_popup li {
+ list-style: none;
+ float: left;
+ width: 53px;
+ height: 50px;
+ border: 1px solid silver;
+ margin: 3px;
+ padding: 10px;
+ text-align: center;
+ font-size: 11px;
+ border-radius: 6px;
+ cursor: pointer;
+}
+.labels {
+ width:70px;
+}
+.error{
+ border: 2px solid @defaultRed;
+}
+.validated{
+ border: 2px solid #4cae4c;
+}
+.notification {
+ width:40%;
+ left:50%;
+ position: relative;
+}
+.redColor{
+ color: @defaultRed;
+}
+.killNode{
+ width: 150px;
+}
+.zoom-buttons {
+ position: absolute;
+ top: 9px;
+ right: 2%;
+}
+.legend {
+ right: 1%;
+
+}
+.globlaPropetiesInfo{
+ width: 80%;
+ left: 10%;
+ position: relative;
+}
+.zoom-buttons .btn {
+ font-size: 8px;
+}
+
+.requiredField {
+ color: @defaultRed;
+}
+#search-bar .twitter-typeahead {
+ position: inherit !important;
+}
+#search-bar .tt-hint {
+ display: none !important;
+}
+#search-bar .bootstrap-tagsinput {
+ width: 260px;
+ border-radius: 0px;
+ line-height: 20px;
+ vertical-align: top;
+ height: 30px;
+ overflow-y: auto;
+}
+#search-bar .bootstrap-tagsinput .label-info{
+ background-color : @bgGreenActive;
+}
+#search-bar .tt-menu {
+ position: absolute;
+ top: 100%;
+ left: inherit !important;
+ z-index: 100;
+ border: 1px solid rgba(0,0,0,0.2);
+ margin-top: 7px;
+ background-color: white;
+ width: 60% !important;
+ padding: 0 5px;
+}
+#job-detail-app-path{
+ overflow-x: scroll;
+}
+
+#search-bar .search-icon {
+ display: inline-block;
+ border: 1px solid #ccc;
+ padding: 4px 10px;
+ border-left: 0px;
+ border-bottom-right-radius: 3px;
+ border-top-right-radius: 3px;
+}
+
+#startDate, #endDate {
+ height: 30px;
+ width: 162px;
+}
+
+.jobTitle {
+ height: 24px;
+ margin-left: 10px;
+ line-height: 30px;
+}
+
+.info {
+ float: left;
+ margin-right: 20px;
+ color: #777;
+ padding-top: 4px;
+}
+
+.pages {
+ margin-right: 40px;
+}
+
+.listing-footer {
+ border-top: 1px solid #d2d2d2;
+ border-bottom: 1px solid #d2d2d2;
+ padding: 3px 0px;
+ margin: 0 0 5px 0;
+}
+
+.page-selector {
+ padding: 4px 12px;
+ border-radius: 0px;
+}
+
+.listing thead {
+ background: #f5f5f5;
+}
+
+.listing th {
+ border-left : 1px solid #ddd;
+ border-bottom: 1px solid #ddd !important;
+}
+
+.listing tr th:first-child {
+ border-left: 0;
+}
+
+.listing > tbody > tr > td {
+ vertical-align: middle;
+ padding: 5px;
+ border-left: 0;
+ border-right: 0;
+}
+
+.job-listing > tbody > tr > td {
+ border-bottom: 1px solid #ddd;
+}
+
+
+.pointer {
+ cursor: pointer;
+}
+
+#job-details .nav-tabs {
+ background: #eee;
+ margin-bottom: 10px;
+}
+
+.preview pre.prettyprint {
+ border: none;
+ background: #fff;
+}
+
+.preview pre {
+ border: none;
+ background: #fff;
+}
+
+.date-picker {
+ position: relative;
+}
+
+.actions-col .loading-container{
+ position: relative;
+}
+
+#bulk-action-loader .loading-container{
+ position: relative;
+}
+
+.decisionNodeHandler {
+ left: 10%;
+ bottom: 30%;
+ position: relative;
+}
+
+.decisionBox {
+ right: 10px;
+ top: 13%;
+ width:75px;
+ position: relative;
+}
+
+.pages .open .dropdown-menu {
+ max-height: 120px;
+ overflow-y: scroll;
+ min-width : 75px;
+ width : 75px;
+}
+
+#action-details .panel-heading {
+ padding: 10px 15px;
+}
+
+#bulk-action-button .dropdown-menu li .fa {
+ margin-right: 10px;
+}
+
+#dashboard, #dashboard .panel, .panel-heading, .panel-body {
+ border-radius: 0px;
+}
+
+#job-details, #job-details .panel, .panel-heading, .panel-body {
+ border-radius: 0px;
+}
+
+#dashboard .listing-error{
+ text-align: center;
+}
+
+#dashboard .panel {
+ border: 0;
+ border-bottom: 1px solid #ddd;
+}
+
+#loading {
+ position: absolute;
+ top: 90px;
+ left: 0;
+ display: none;
+ width: 100vw;
+ height: 80vh;
+ overflow: hidden;
+ z-index: 1;
+}
+
+.loader img {
+ height: 40px;
+ width: 50px;
+}
+
+#search-table {
+ margin-bottom: 0px;
+}
+
+#search-table .bulk-actions-buttons {
+ margin-left: -124px;
+ margin-top: 3px;
+ position: fixed;
+ transition: all .5s ease;
+}
+
+#search-table .bulk-actions-buttons:before {
+ display: block;
+ content: "";
+ width: 0;
+ height: 0;
+ left: -10px;
+ top: 10px;
+ border: 5px solid transparent;
+ border-right: 10px solid #666;
+ position: absolute;
+}
+
+#search-table .bulk-actions-buttons.shown {
+ margin-left: 30px;
+}
+
+#search-table .actions-col {
+ white-space: nowrap;
+ text-align: center;
+ min-width: 150px;
+ }
+
+ .btn-kill:hover,
+ .btn-kill:focus {
+ background: #d9534f;
+ color: #fff;
+ border-color: @defaultRed;
+ }
+
+ .actions-col .btn {
+ color: gray;
+ cursor: not-allowed;
+ opacity: .5;
+ font-size: 10px;
+ }
+
+ .actions-col .btn.isOn {
+ color: #000;
+ cursor: pointer;
+ opacity: 1;
+ }
+ .pages .btn {
+ /*color: @bgGreenActive;*/
+ }
+
+ .pages .btn.disabled {
+ color: gray;
+ }
+
+ .pages .btn-primary {
+ color: #fff;
+ }
+ .cbox {
+ width: 20px;
+ }
+
+ .main-panel {
+ padding: 0px;
+ }
+
+ #dashboard .main-panel {
+ padding: 5px;
+ }
+
+ .first-col {
+ text-align: center;
+ }
+
+
+
+.DONEWITHERROR,
+.FAILED,
+.KILLED {
+ color: #d9534f;
+}
+
+.RUNNING {
+ color: green;
+}
+
+.PAUSED,
+.PAUSEDWITHERROR,
+.PREPPAUSED,
+.RUNNINGWITHERROR,
+.SUSPENDED,
+.SUSPENDEDWITHERROR {
+ color: #f0ad4e;
+}
+
+.SUCCEEDED {
+ color: #5cb85c;
+}
+
+.mb0 {
+ margin-bottom: 0;
+}
+
+.pb5 {
+ padding-bottom: 5px;
+}
+
+.navbar-header {
+ width: 100%;
+}
+
+#create-new-button {
+ float: right;
+ padding-top: 8px;
+}
+
+.width100Per{
+ width: 100%;
+}
+.hdfs-browse{
+ max-height: 500px;
+ overflow: scroll;
+}
+#wf_title{
+ margin-left: 2px;
+ width: 150px;
+ font-size: 12px;
+}
+.backto-dashboard{
+ text-decoration: blink !important;
+}
+.file-upload-control input[type="file"]{
+ width: 200px;
+ display: inline;
+ border: 1px solid #ccc;
+}
+.file-upload-control input[type="button"], input[type="submit"], input[type="reset"], input[type="file"]::-webkit-file-upload-button, button {
+ padding: 6px 12px;
+ border-radius: 4px;
+ background-color: #fff;
+ line-height: 1.42857143;
+ border: none;
+}
+.close-icon{
+ font-size: 18px;
+ font-weight: bold;
+ line-height: 1;
+ text-shadow: 0 1px 0 #fff;
+ color: #AFAFAF;
+ background: transparent;
+ padding: 3px;
+}
+#flow-designer{
+ position: relative;
+ top:10%;
+}
+.designer-main-panel{
+ position: relative;
+ width: 100%;
+ border: none;
+ height: 0px;
+}
+.connector_overlay_new {
+ white-space: nowrap;
+ border: 1px solid #ddd;
+ background: #E5E5E5;
+ border-radius: 30px;
+ width: 24px;
+ height: 24px;
+ line-height: 24px;
+ text-align: center;
+ cursor: pointer;
+ transform: scale(0.8);
+ font-size: 12px;
+}
+.connector_overlay_new:hover .node_actions{
+ opacity: 1;
+}
+.placeholder-node{
+ width:1px;
+ height: 1px;
+ background: transparent;
+ padding-left: 0px;
+ padding-right: 0px;
+ margin-left: 4px;
+ /* transform: translate(0%, -6%);*/
+}
+.decision_end{
+ width: 10px;
+ height: 10px;
+ border-radius: 16px;
+}
+#decision-properties-table {
+ width: 70%;
+ margin-left: 50px;
+}
+.preview-xml{
+ border: none;
+ padding: 8px;
+}
+.workflow-actions-pop{
+ width: 250px;
+}
+#killnodes-container{
+ width: 300px;
+ height: 100px;
+ padding: 5px;
+ border-radius: 3px;
+}
+.decision-add-branch-popover{
+ position: absolute;
+ left: 44px;
+ top: -7px;
+ z-index: 5;
+}
+
+.jsplumb-connector { z-index:1; }
+.jsplumb-endpoint { z-index:2; }
+.jsplumb-overlay { z-index:3; }
+#selector-content .panel-body{
+ width:400px;
+}
+
+.decisionSplit {
+ border-radius: 24px;
+ width: 24px;
+ height: 24px;
+ left: 70% !important;
+ top: 67% !important;
+ transform:rotate(315deg) !important;
+}
+
+.forkSplit {
+ border-radius: 24px;
+ width: 24px;
+ height: 18px;
+ left: 50% !important;
+ top: 75% !important;
+}
+
+.control_flow_node {
+ cursor: not-allowed;
+}
+.join {
+ background: #fff;
+}
+.default-condition{
+ background-color: blue;
+}
+.query-text-area {
+ width: 540px;
+}
+.decisionText{
+ position: absolute;
+ transform: rotate(315deg);
+ top: 30%;
+ left: 0px;
+ right: 0px;
+}
+.decisionIcon{
+ position: relative;
+ right: 5px;
+}
+.actionNodes li{
+ padding: 10px 0px !important;
+ height: auto;
+}
+.dr_action_fork{
+ width: 45px !important;
+ height: auto !important;
+ padding: 10px 0px !important;
+ border-radius: 0px !important;
+}
+.dr_action_switch{
+ width: 45px !important;
+ height: 45px !important;
+ padding: 10px 0px !important;
+}
+.paddingClass{
+ padding-top: 0.5%;
+}
+.margin0{
+ margin-bottom: 0px;
+}
+.editor-icon-title span{
+ padding-left: 5px;
+}
+.icon_map_red{
+ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAMUklEQVR4Xu2df2xb1RXHz7nPTpxQykZL+VEajbYbjMFgoCE2xoYG2g9NG6OlCNbEiX/QCFALWtXaTifwYE2ctCui/GxInhM7CEaL2JjEH9uQ+KHBNsQPsQ5UBkVN+bEVutKmaZ3E757puT9kPzvxi/P8bPed/Nfne88593s/77zXe++7F4H/HK0AOrr13HhgABwOAQPAADhcAYc3nzMAA+BwBRzefM4ADIDDFXB48zMZoLlHvURoeDEACSfoQYIIJb2eiATfcEJ7p2ojtsT6b0PABxwnhJREiLcmI4FHHNf2rAajN9b3GYCY40gRNPgssc5/miPbfrTR6I2p5GQBEmG/o1+E8wCQRG8JxMMnJBRSawShXJjdNgbAkAFIkxcm1wW3n4gAtPXEL5aScl78GAAGgB8B2Xc7Z4ATMfdN3qa8dwAGgAHgdwAHMcAZgP8bmDsOwI8AB93+AMAZgDMAZwBn3fO5reUMwBmAMwBngCwF+CVwchxWbNniHt9bt0jxaHv6fxn831TgRKNR8V792QvrBB5SQ4GPi0Hm+426ABVwq2HfB4Bo2wQdPwJMPgK8sf4fg4QBEDgPpNRQKPefk9q1OhqNSmPnLu9Uz1cItoECX838RvCMS1CzGgqMGMvetHHLXHfa9QQAXn2kKLwGirYsuebmD4pBY8XvDIAJAJrXbzkTFPd7AqAxW3QEuHUw7H84+9qyJ59UGt4/8A6g+HLOEDtCbzLkbzd2Wkssvg2BluaUlfiPZKTtcjsyAQNgAgBvt9oKBAP5dxw9lwgHrsm+3hzrv0gAvplfVu5NhINzs69fFY26mjxN+tS7y1heQ23BY6GbP7TiLp/KBgNgAoCWWPxGBHo8T0iUzyZCwZ9kX2/rjJ8nBb2TV1bCx4kO//zs6/p7ws66+
QdBKA3G8qS4Tk+u8e5hACxUoNT1AMujQ7OxLrVDCHFGTjhESxKRwNOGa9jco74kCK8wPC7uHgz77zI2pzUWf4CAbsu1Ac8kIv5rLWz6pKY4A5jIALp6Lev7LkAQD0sFvi0kfEwC706GfY8WUrZlQ2IeaNpDCNpPAcQoETyye2z4zuej0bSx/MrNm+s/H53VQwQ+ENItCLd6ML2yN9y+nwGwWIFSM4AxbRd68y8YKtGRxSZm/ls3nbIW6sIZwGQGsFDzqjLFADAAPBRcVbekzcFwBuAMwBnA5psux92y6JN1jQ0HO6UGPgJwCwFbXUh3FBo2LkecnAEqnAFautT7EGFVdudKgKeHwv4l5ehwo00GoIIAZGYMPU0jxjkGvZMUCfPiHf5Pyw0BA1BBADJzAXVnp0AIxdjRShqa4r/y72YALFTAioEgC8PJmGqN9T9NgD/PtqtPCSdDvm+aGkCaYUCcASqYATJDzBsS80jTtgqg7+r/1j/OBaClQ5HgezPsW1PVGYAKA5DpJSL0x+LnjAtyD631v2vHnX+MDgagGgAwda+WpxADwADwQFB57q3asMoZgDOAcY8g6gTET2qD32lGqeF8EBTOrlXxHUKI0NsdXw5APiRyEypbF6Z2PWh6zcE0JSg6EjhDe9OrTvACSFBAge9Mr6J1pSsNQEt3/x1IeG9ui2hTIhxYbV0rJ7ekPwImCq1KLbtzKUcPL559yhf37ROH9rpHhID6svvMcyDHE+FgBfweDUS/+zvje0CBnNXCAJDWUnVzHos2Hyi3JlhoXXq5nR63TxgGBAWA1tvmM9sRyt8lQsEbK+IbAPQvjVL73OOF/LsIFqkR/85yx4bLog/OavA03EUAlyKBM7aKRZAC4FWpuO5OrvGOllvkqex7u9WXgeBbOWUkDB9ePGvh1htu0ModW/l3yCLCtl8PlJRmB+5qG7NzVKzcYheyn1ltrCh/AqAzj/6+nwRcm1zrf8GOeMoOgLdLfQ
UQLi+lMRLwxaGw73ul1K2lOnoW9jQ0/gAlud318s/FPjy1sm1lB6C5U02V/IIn5WiiIzjLygazrVwFGACHE8EAMADlVYAfAeXVd6bWy5oB2nriZ6TTNCwEuEsJVIJMaRp96fF1N/+3lPpcp7gCZQFAf6tt9DSsISlXgxAnFQ9jyhIHAanHczj9295o+6EZ2uLqBgUsBSCzO8bOg0EpZTTvU+qZSq9/kavQnYsO747bNVEy05Brob5lADT3xK8UE7Tl+L445Wo9wnbQaEWiI/BKuVw4ya5lALTG4veS1FbaIp6ibEqEfGut9KVnr0/fftsyPayMzWpbp51/Ph0bZnZEg6cSsDU28DUC+RgAXGS10FVu7w0h8ReOB8AbU18HgG9UeWeVK7y/MwAOPjVNSphgABwMQGbDy3Llllqxazw3USJeh2nNlq9y7NZICDyXELcd98sAABgBcNReyQwAA8CPACefm8gZgDOArRlAnx2URD8kwjGZcj9rx7LnYi9a/A5QTCGLfm/riv8ojfTUse1QpJT/UYTrmsFw278sclGSGQagJNmmV0lf/z62z72bAE7ProkkXxqMBDMbI1TqjwGwQfnJtlCXAHJxathdyeldBsAGAAKb+k6dSMGevM2QJHyY6PAvsCGESV0wADapn5kuBroj2x0Brphsy3WbwuKBILuE1vfE+8DT1E76+ThIYyCxL++wBbuCyfLDGaAColeTSwagmnqjArEwABUQvZpcMgDV1BsViIUBsFF0feFl/c6RC1xSjA1E2nZUw6ffDIBNAGSOU0X5+2Mnakqkv6JwL7HjbLypmsgA2ABA5oBEd9N24zcDBPhUMuy73oYQeCAIAPI2y7ZrOri5q2+xQPHv/F6Q44lQwFPJRwFnABtuP393/1lpwo8KuNqXCPnmMAA2dEIlM4DePG+X+gdA+FnOUDBBVzLi77Cn+YW9cAawSX1/d//JE4AbkeRSkGIMBfTtSg3fU+g4VZtCyrh
hAOxUuwp9MQBV2Cl2hsQA2Kl2FfpiAKqwU+wMiQGwU20A0I9KuwpAmlkGpg8gPQ8gTL0oEuGK3l5Xb3u7vvm16T8GwLRUMyt408Ytc13pukcQ6FqQ2gQKlzq7cWT1/atWjRkt68epeuoPbiCEoJCyHgX+USru9oLDxkTY0qPejmlcl9l1m+BvAnHFQNj3TzMRMwBmVLKgjDfW/xcAvNowDrA5GfHfbjTf2q1uJIKc/fIz28aG2q4yDhp5Y2ozACRzbeAnLpTnmjl/lwGwoHOLmfD9Rl2guWDYWE5KGBmK+E4xdmpLp7oXBZxqLF9oC3VvrP85APy+sSwSXT8YCTxVLDYGoJhCFvzu71IXphHezwMAZGooFGg0AtDcqR4QAk7OK4903lAosCP7emtX34uE4kpjWQK8KRn2PVEsfAagmEJW/K4/p7vjryLApTnmiJKJSMBrdOGNqf0A4M++rp+oORT2X5z/CIivBKDNBhv7QSqLEh2te4uFzwAUU8ii31s2PHoOTLieQEGXZUwSPOPBCW9vuH2/0YU+bDxOOCgArjtSFF4jkjcWOk41M9XsWbABAPUj2F0gYVggtg5EfM+bCZ0BMKOSVWWIcHlP33wh6sfNLATxdaqngQRPfJ3vw2IzhsujQ7Pr68fnjiyatWs6J20YARCEl42OHXrHqiZXk52GOs+FIPDl4zHZtR6gmkQo8LihisUn5RHfQtj6lTYDkNXjxgxgFwz6Dl0ClAs00FwKyLfyPpuzJ5B0Zcizp3GmvHhj/TsA8CumCltaSI4rabE4Xa+5UFPercjRfQjbHQ+AvsexImmr8dN1S/t6EmNSwpgQEgFEnR3+cn3gJyDlUscDoIuiz080eRaeJUhzxLF5EhV5eKHnI/1lmQEo863XGlNvkYRXlOJGAL04GPH3llLXbB0GwKxSJZbzdj56CITSUFp1eSARDp5SWl1ztRgAczqVXKraz0xiAEruWnMVGQBzOp2wpRiAE7Zr
zTWMATCn0wlX6ujncN0AsGQmjZMA2xQhwoNr2/Km02di91hdfgewQsUsG97OwTmE2p1EcEup5yXmhyTHEZSHXHXaPVYfLM0AWATAys2b6/ePnrRKInUIEF+wyGyOGQnycwXE+tmNB+8vtJayFJ8MQCmqFajT0qXehwj6mgQb/mhTIhzIWTNZqlMGoFTlDPWae9RLUKOvW2RuSjOKIt4cWOt70wpfDIAVKtawDQaghjvPitAZACtUrGEbDEANd54VoTMAVqhYwzYYgBruPCtCZwCsULGGbTAANdx5VoTOAFihYg3b+D/35R/ptIYQMwAAAABJRU5ErkJggg==)
+}
+.node_actions i{
+ border-right: 1px solid #ababab;
+ border-radius: 0px;
+ min-width: 26px;
+}
+.node_actions i:last-child {
+ border-right:none;
+}
+.wf-path {
+ font-size: 12px;
+ float: left;
+ color: gray;
+ margin-top: 17px;
+ max-width: 150px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+.cred-type{
+ font-size: 12px;
+ color: gray;
+ margin-left: 5px;
+}
+.labelCheckbox{
+ padding-left:35px !important;
+}
+.file-op-setting{
+ padding-left: 105px;
+}
+.rightAlign{
+ text-align: left !important;
+}
+.bottom-margin-zero{
+ margin-bottom: 5px !important;
+}
+#credentials_config .fa-trash-o{
+ color: @defaultRed;
+ cursor: pointer;
+}
+.credential-list {
+ margin-top: 37px;
+}
+.credential-list .fa-trash-o{
+ color: @defaultRed;
+ cursor: pointer;
+}
+.credential-list .fa-pencil{
+ color : @bgGreenActive;
+ cursor: pointer;
+}
+.check-class{
+ padding-left: 3%;
+}
+.popover-title{
+ background-color:#fff
+}
+.centralize-panel{
+ margin-left: 17%;
+}
+.dataset-list {
+ margin-top: 37px;
+}
+
+.dataset-list .fa-trash-o{
+ color: @defaultRed;
+ cursor: pointer;
+}
+
+.dataset-list .fa-pencil{
+ color : @bgGreenActive;
+ cursor: pointer;
+}
+
+.node {
+ stroke: #fff;
+ stroke-width: 2px;
+}
+
+.link {
+ fill: none;
+ stroke: #000;
+}
+
+.cy-panel {
+ height: 500px;
+ position: relative;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+}
+
+.cy-panzoom {
+ left: 90%;
+ z-index: 999;
+}
+
+.overlay_node_editor {
+ position: absolute;
+ z-index: 100;
+ overflow: hidden;
+ margin-top: 3px;
+ margin-left: 5px;
+ display: none;
+}
+
+.overlay-node-label {
+ position: absolute;
+ z-index: 100;
+ display: none;
+ background-color: #fbfbfb;
+ min-width: 110px;
+ border: 1px solid #999;
+ padding: 0 5px;
+ height: 18px;
+ font-size: 12px;
+}
+
+#cyRenderer .editable {
+ padding: 7px 10px;
+ border: 1px solid #999;
+ background: #fff;
+ cursor: text;
+ white-space: nowrap;
+ text-align: left;
+ width: 140px;
+}
+
+#cyRenderer .error {
+ padding: 5px 10px;
+ border: 1px solid @defaultRed;
+ background: #fff;
+ cursor: text;
+ white-space: nowrap;
+ text-align: left;
+ width: 140px;
+}
+
+#cyRenderer input:invalid {
+ border: 1px solid @defaultRed;
+}
+
+.decision-condition-label {
+ border-bottom: 1px solid #D0D0D0;
+ padding: 3px;
+ min-width: 120px;
+}
+
+.decision-condition-header {
+ font-weight: bold;
+}
+
+.overlay-transition-content,
+.overlay-node-actions {
+ position: absolute;
+ z-index: 100;
+ overflow: hidden;
+ display: none;
+ border: 1px solid #999;
+ background: #fff;
+ border-radius: 3px;
+ min-width: 25px;
+}
+
+.overlay-node-actions {
+ height: 32px;
+ cursor: pointer;
+ padding: 2px;
+}
+
+.overlay-transition-actions {
+ float: right;
+ height: 30px;
+ cursor: pointer;
+ padding: 2px;
+}
+
+.overlay-node-actions span {
+ display: none;
+}
+
+.overlay-transition-actions span i,
+.overlay-node-actions span i {
+ min-width: 20px;
+ padding: 5px;
+ border: 1px solid transparent;
+ border-radius: 2px;
+}
+
+.overlay-transition-actions span i:hover,
+.overlay-node-actions span i:hover{
+ border: 1px solid #ababab;
+}
+
+.overlay-trash-transition-icon .fa-trash-o,
+.overlay-trash-icon .fa-trash-o {
+ color: @defaultRed;
+}
+
+.overlay-plus-icon .fa-plus-square {
+ color: @bgGreenActive;
+}
+.cyScrollMsg {
+ text-align: center;
+}
+
+.cyScrollMsgContent {
+ width: 30px;
+ background-color: #ccc;
+}
+
+.text-bold {
+ font-weight: bold;
+}
+
+.green-border {
+ border-color: green;
+}
+
+.configuration-property-table .propertyName {
+ word-break: break-all;
+ width: 20%;
+}
+
+.configuration-property-table .propertyValue {
+ width: 80%;
+ word-break: break-all;
+}
+
+.undo {
+ cursor: pointer;
+}
+
+.paste-action {
+ font-size: 10px;
+}
+
+.paste-action-btn {
+ border: 1px solid silver;
+ border-radius: 6px;
+ margin-left: 5px;
+ margin-bottom: 4px
+}
+#notificationWidget{
+ width: 20%;
+ float: left;
+ position: fixed;
+ top: 15%;
+ left: 66%;
+ word-break: break-all;
+ height: 50%;
+ max-height: 600px;
+ overflow-y: scroll;
+ z-index: 1040;
+}
+
+.closeTab {
+ margin-left: 10px;
+ cursor: pointer;
+ color: @defaultRed;
+}
+
+.tab-panel-heading {
+ margin-top: 2px;
+}
+
+.borderTopNone {
+ border-top: none;
+}
+
+.borderRadiusNone {
+ border-radius: 0px;
+}
+
+.borderRightRadiusNone {
+ border-top-right-radius: 0px;
+ border-bottom-right-radius: 0px;
+}
+
+.kill-message {
+ font-style: italic;
+ color: gray;
+}
+
+.ok-to-warning {
+ font-style: italic;
+ color: #8a6d3b;
+ background-color: #fcf8e3;
+}
+
+.kill-nodes-list {
+ height: 200px;
+ overflow-y: auto;
+}
+
+.kill-nodes-list .fa-trash-o{
+ color: @defaultRed;
+ cursor: pointer;
+}
+
+.kill-nodes-list .fa-pencil{
+ color : @bgGreenActive;
+ cursor: pointer;
+}
+
+#killnode-manager-dialog .panel-footer {
+ background-color: #fff;
+}
+
+.plr0px {
+ padding-left: 0px;
+ padding-right: 0px;
+}
+#stackTrace{
+ white-space: pre-wrap;
+ max-width: 100%;
+ max-height: 400px;
+ overflow: scroll;
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-config.hbs
new file mode 100644
index 0000000..27168a4
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-config.hbs
@@ -0,0 +1,129 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="main">
+ <nav class="navbar navbar-default mb0 borderTopNone">
+ <div class="container-fluid container-custom">
+ <div class="navbar-header">
+ <div class="form-inline col-xs-6 paddingtop8">
+ <div class="form-group {{if (v-get this 'bundle.name' 'isInvalid') 'has-error'}}" >
+ <label for="wf_title">Name<span class="requiredField"> *</span></label>
+ {{input class="form-control" type="text" name="bundle_title" value=bundle.name title="Bundle Name" placeholder="Bundle Name"}}
+ {{#if (v-get this 'bundle.name' 'isInvalid')}}
+ <span class="text-danger" title="Name is required"><i class="fa fa-close"></i>Name is required</span>
+ {{/if}}
+ </div>
+ </div>
+ <div class="navbar-brand pull-right paddingtop8 col-xs-18">
+ <div class="btn-group" role="group" aria-label="...">
+ <button type="button" class="btn btn-default" data-toggle="modal" data-target="#ConfirmDialog" title="New Workflow" {{action "confirmReset"}}>
+ <i class="fa fa-refresh"> Reset</i>
+ </button>
+ <button type="button" class="btn btn-default" title="Import workflow" {{action "openFileBrowser" "bundleFilePath"}}>
+ <i class="fa fa-download"> Import</i>
+ </button>
+ <button id="import-bundle-test" type="button" class="btn btn-default hide" title="Import Bundle Test" {{action "importBundleTest"}}>
+ <i class="fa fa-download"></i>
+ </button>
+ <div class="btn-group">
+ <div class="dropdown">
+ <button class="btn btn-default dropdown-toggle borderRadiusNone" type="button" data-toggle="dropdown"><i class="marginright5"></i>More
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu">
+ <li>
+ <a href="javascript:void(0)" data-toggle="modal" data-target="#previewModal" title="Preview Xml" {{action "preview"}}>
+ <i class="fa fa-eye marginright5"></i>Preview xml
+ </a>
+ </li>
+ <!-- <li>
+ <a href="javascript:void(0)" data-toggle="modal" title="Download workflow" {{action "downloadWorkflowXml"}}>
+ <i class="fa fa-download marginright5"></i>Download xml
+ </a>
+ </li> -->
+ </ul>
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary" title="Submit Bundle" {{action "submitBundle"}}>
+ <i class="fa fa-upload"> Submit</i>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </nav>
+ <div class="container-fluid">
+ <form class="form-horizontal">
+ <div class="col-sm-12 paddingtop10">
+ <div class="col-sm-8 centralize-panel">
+
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Coordinators</h4>
+ <button id="coordinator-create-btn" {{action 'createCoordinator'}} type="button" class="btn btn-default pull-right">
+ <i class="fa fa-plus-circle"></i> Add Coordinator
+ </button>
+ </div>
+ <div class="panel-body">
+ <ul class="list-group">
+ {{#each bundle.coordinators as |coordinator index|}}
+ <li class="list-group-item">
+ {{coordinator.name}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteCoordinator" index bubbles=false}}></i>
+ </span>
+ <span class="pull-right paddingright10">
+ <i class="fa fa-pencil" title="Edit" {{action "editCoordinator" index bubbles=false}}></i>
+ </span>
+ </li>
+ {{else}}
+ <li class="list-group-item">No Coordinators Configured.</li>
+ {{/each}}
+ </ul>
+ {{#field-error model=this field='bundle.coordinators' showErrorMessage=true}}{{/field-error}}
+
+ {{#if coordinatorCreateMode}}
+ {{#bundle-coord-config coordinator=currentCoordinator openTab="openTab" openFileBrowser="openFileBrowser" add="addCoordinator" cancel="cancelCoordinatorOperation" createMode=coordinatorCreateMode}}{{/bundle-coord-config}}
+ {{/if}}
+ {{#if coordinatorEditMode}}
+ {{#bundle-coord-config coordinator=currentCoordinator openTab="openTab" openFileBrowser="openFileBrowser" update="updateCoordinator" cancel="cancelCoordinatorOperation" editMode=coordinatorEditMode}}{{/bundle-coord-config}}
+ {{/if}}
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-body">
+ {{#date-with-expr inputName="kickOffTime" label="Kick off Time" inputPlaceholder="Kick Off Time" dateField=bundle.kickOffTime}}{{/date-with-expr}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+</div>
+{{#if showingFileBrowser}}
+ {{hdfs-browser closeFileBrowser="closeFileBrowser" selectFileCallback=selectFileCallback filePath=filePath}}
+{{/if}}
+{{#if showingJobConfig}}
+ {{job-config type='bundle' closeJobConfigs="closeBundleSubmitConfig" jobFilePath=bundleFilePath openFileBrowser="openFileBrowser" closeFileBrowser="closeFileBrowser" jobConfigs=bundleConfigs}}
+{{/if}}
+{{#if showingResetConfirmation}}
+ {{#confirmation-dialog title="Confirm Bundle Reset"
+ confirmationMessage="Any unsaved changes may be lost. Do you want to proceed resetting the bundle ?"
+ okBtnText="Continue" cancelBtnText="Cancel" onOk="resetBundle"}}{{/confirmation-dialog}}
+{{/if}}
+{{#if showingPreview}}
+ {{#preview-dialog title="Bundle XML Preview" previewXml=previewXml}}{{/preview-dialog}}
+{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-coord-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-coord-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-coord-config.hbs
new file mode 100644
index 0000000..86a49b9
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-coord-config.hbs
@@ -0,0 +1,58 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="well">
+ <div class="form-group">
+ <label class="control-label col-xs-2">Coordinator Name<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ {{input type="text" class="form-control" name="name" value=coordinator.name placeholder="Coordinator Name"}}
+ {{#field-error model=this field='coordinator.name' showErrorMessage=showErrorMessage}}{{/field-error}}
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="control-label col-xs-2">Coordinator Path<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ <div class="input-group">
+ {{input type="text" class="form-control" name="appPath" focus-out="showCoordinatorName" value=coordinator.appPath placeholder="Path of the coordinator file"}}
+ <span class="input-group-btn">
+ <button class="btn btn-primary" type="button" {{action "openFileBrowser" "coordinator.appPath"}}>Browse</button>
+ <button class="btn btn-default" type="button" {{action "openTab" 'coord' coordinator.appPath}} name="button"><i class="fa fa-external-link"></i></button>
+ </span>
+ </div>
+ {{#if coordinatorName}}
+ <span title="Name of the coordinator">({{coordinatorName}})</span>
+ {{/if}}
+ {{#field-error model=this field='coordinator.appPath' showErrorMessage=showErrorMessage}}{{/field-error}}
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading">Configuration</div>
+ <div class="panel-body handlerPanel">
+ {{#name-value-config configuration=coordinator.configuration}}{{/name-value-config}}
+ </div>
+ </div>
+ <div class="form-group">
+ <div class="col-xs-7 pull-right">
+ <button id="coordinator-cancel-btn" {{action 'cancelCoordinatorOperation'}} type="button" class="btn btn-default">Cancel</button>
+ {{#if createMode}}
+ <button id="coordinator-add-btn" {{action 'addCoordinator'}} type="button" class="btn btn-primary">Add</button>
+ {{else}}
+ <button id="coordinator-update-btn" {{action 'updateCoordinator'}} type="button" class="btn btn-primary"> Update </button>
+ {{/if}}
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-job-details.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-job-details.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-job-details.hbs
index b1f1d7e..f6b491b 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-job-details.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/bundle-job-details.hbs
@@ -95,7 +95,22 @@
<div role="tabpanel" class="tab-pane" id="jobConfig">
<div class="panel panel-default">
<div class="panel-body preview">
- <pre class="prettyprint">{{model.conf}}</pre>
+ <table class="table table-striped configuration-property-table">
+ <thead>
+ <tr>
+ <th class="propertyName">Name</th>
+ <th class="propertyValue">Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each model.configurationProperties as |configurationProperty|}}
+ <tr>
+ <td class="propertyName">{{configurationProperty.name}}</td>
+ <td class="propertyValue">{{configurationProperty.value}}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
</div>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/conditional-data-input.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/conditional-data-input.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/conditional-data-input.hbs
new file mode 100644
index 0000000..03eb0d8
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/conditional-data-input.hbs
@@ -0,0 +1,64 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="form-inline">
+ <select onchange={{action (mut condition.operator) value="target.value"}} name="select-input" class="form-control" data-show-icon="true">
+ {{#each conditionsList as |condition index|}}
+ <option value={{condition.value}} selected={{eq condition.operator condition.value}}>{{condition.displayName}}</option>
+ {{/each}}
+ </select>
+ {{#if (not (eq condition.operator "combine"))}}
+ <button id="data-add-btn" {{action 'addCondition'}} type="button" class="btn btn-default form-control">
+ <i class="fa fa-plus-circle"></i> Condition</button>
+ {{/if}}
+ <button id="data-add-btn" {{action 'addDataInput'}} type="button" class="btn btn-default form-control">
+ <i class="fa fa-plus-circle"></i> Data Input</button>
+ {{#if showAdvanced}}
+ {{input type="text" class="form-control" name="conditionName" title="Condition Name" value=condition.name placeholder="Condition Name"}}
+ {{input type=text class="form-control" value=condition.min placeholder="Mininum Inputs"}}
+ {{input type=text class="form-control" value=condition.wait placeholder="Wait Time"}}
+ <button id="data-add-btn" {{action 'hideAdvanced'}} type="button" title="Configure Advanced Options" class="form-control btn btn-default">
+ <i class="fa fa-chevron-left"></i> Advanced
+ </button>
+ {{else}}
+ <button id="data-add-btn" {{action 'showAdvanced'}} type="button" title="Configure Advanced Options" class="form-control btn btn-default">
+ <i class="fa fa-chevron-right"></i> Advanced
+ </button>
+ {{/if}}
+ {{yield}}
+ {{field-error model=this field='condition.operator' showErrorMessage=showErrorMessage}}
+ {{field-error model=this field='condition.operands' showErrorMessage=showErrorMessage}}
+</div>
+<ul class="list-group">
+ {{#each condition.operands as |operand index|}}
+ <li class="list-group-item">
+ {{#if (eq operand.type 'condition') }}
+ {{#conditional-data-input condition=operand datasets=datasets}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteOperand" index bubbles=false}}></i>
+ </span>
+ {{/conditional-data-input}}
+ {{else}}
+ {{#data-input datasets=datasets dataInput=operand register="registerChild" deregister="deregisterChild"}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteOperand" index bubbles=false}}></i>
+ </span>
+ {{/data-input}}
+ {{/if}}
+ </li>
+ {{/each}}
+</ul>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/confirmation-dialog.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/confirmation-dialog.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/confirmation-dialog.hbs
new file mode 100644
index 0000000..fc86286
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/confirmation-dialog.hbs
@@ -0,0 +1,34 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="ConfirmDialog" class="modal fade" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">{{title}}</h4>
+ </div>
+ <div class="modal-body">
+ {{confirmationMessage}}
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{cancelBtnText}}</button>
+ <button type="button" class="btn btn-primary" {{action "onOk"}} data-dismiss="modal">{{okBtnText}}</button>
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-config.hbs
new file mode 100644
index 0000000..a6edcec
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-config.hbs
@@ -0,0 +1,352 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="main">
+ <nav class="navbar navbar-default mb0 borderTopNone">
+ <div class="container-fluid container-custom">
+ <div class="navbar-header">
+ <div class="form-inline col-xs-6 paddingtop8">
+ <div class="form-group {{if (v-get this 'coordinator.name' 'isInvalid') 'has-error'}}">
+ <label for="wf_title">Name </label>
+ {{input class="form-control" type="text" name="coord_title" value=coordinator.name title="Coordinator Name" placeholder="Coordinator Name"}}
+ {{#if (v-get this 'coordinator.name' 'isInvalid')}}
+ <span class="text-danger" title="Name is required"><i class="fa fa-close"></i>Name is required</span>
+ {{/if}}
+ </div>
+ </div>
+ <div class="navbar-brand pull-right paddingtop8 col-xs-18">
+ <div class="btn-group" role="group" aria-label="...">
+ <button type="button" class="btn btn-default" data-toggle="modal" data-target="#ConfirmDialog" title="New Workflow" {{action "confirmReset"}}>
+ <i class="fa fa-refresh"> Reset</i>
+ </button>
+ <button type="button" class="btn btn-default" title="Import workflow" {{action "openFileBrowser" "coordinatorFilePath"}}>
+ <i class="fa fa-download"> Import</i>
+ </button>
+
+ <button id="import-test" type="button" class="btn btn-default hide" title="Import coordinator Test" {{action "importCoordinatorTest"}}>
+ <i class="fa fa-download"></i>
+ </button>
+ <button type="button" class="btn btn-default" title="Parameters Configuration" {{action "showParameterSettings" true}}>
+ <i class="fa fa-cog marginright5"></i>Parameters
+ </button>
+ <button type="button" class="btn btn-default" data-toggle="modal" data-target="#control-dialog" title="Coordinator Controls" {{action "showControlConfig"}}>
+ <i class="fa fa-wrench marginright5"></i>Controls
+ </button>
+ <div class="btn-group">
+ <div class="dropdown">
+ <button class="btn btn-default dropdown-toggle borderRadiusNone" type="button" data-toggle="dropdown"><i class="marginright5"></i>More
+ <span class="caret"></span></button>
+ <ul class="dropdown-menu">
+ <li>
+ <a href="javascript:void(0)" data-toggle="modal" data-target="#previewModal" title="Preview Xml" {{action "preview"}}>
+ <i class="fa fa-eye marginright5"></i>Preview xml
+ </a>
+ </li>
+ <!-- <li>
+ <a href="javascript:void(0)" data-toggle="modal" title="Download workflow" {{action "downloadWorkflowXml"}}>
+ <i class="fa fa-download marginright5"></i>Download xml
+ </a>
+ </li> -->
+ </ul>
+ </div>
+ </div>
+ <button type="button" class="btn btn-primary" title="Submit Coordinator" {{action "submitCoordinator"}}>
+ <i class="fa fa-upload marginright5"></i>Submit
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </nav>
+ <div class="container-fluid">
+ <form class="form-horizontal">
+ <div class="col-sm-12 paddingtop10">
+ <div class="col-sm-8 centralize-panel">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <div class="form-group">
+ <label class="control-label col-xs-2">Workflow Path<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ <div class="input-group">
+ {{input type="text" class="form-control" name="appPath" focus-out="showWorkflowName" value=coordinator.workflow.appPath placeholder="Path of the workflow file"}}
+ <span class="input-group-btn">
+ <button class="btn btn-primary" type="button" {{action "openFileBrowser" "coordinator.workflow.appPath"}}>Browse</button>
+ <button class="btn btn-default" type="button" {{action "openTab" 'wf' coordinator.workflow.appPath}} name="button"><i class="fa fa-external-link"></i></button>
+ </span>
+ </div>
+ {{#if workflowName}}
+ <span title="Name of the workflow">({{workflowName}})</span>
+ {{/if}}
+ {{#field-error model=this field='coordinator.workflow.appPath' showErrorMessage=showErrorMessage}}{{/field-error}}
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="control-label col-xs-2">Frequency<span class="requiredField"> *</span></label>
+ <div class="col-xs-2">
+ <select class="form-control" name="frequency-type" title="Frequency type" onchange={{action (mut coordinator.frequency.type) value="target.value"}}>
+ {{#each timeUnitOptions as |timeUnit|}}
+ <option value={{timeUnit.value}} selected={{eq timeUnit.value coordinator.frequency.type}}>{{timeUnit.displayName}}</option>
+ {{/each}}
+ </select>
+ {{#field-error model=this field='coordinator.frequency.type' showErrorMessage=showErrorMessage}}{{/field-error}}
+ </div>
+ <div class="col-xs-3">
+ {{input class="form-control" type="text" value=coordinator.frequency.value placeholder="frequency" title="Periodic intervals at which datasets that are produced, and coordinator applications are scheduled to run"}}
+ {{field-error model=this field='coordinator.frequency.value' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ {{#date-with-expr required=true inputName="start" label="Start" inputPlaceholder="Start Time" dateField=coordinator.start timezone=coordinator.timezone register="registerChild" deregister="deregisterChild"}}{{/date-with-expr}}
+ {{#date-with-expr required=true inputName="end" label="End" inputPlaceholder="End Time" dateField=coordinator.end timezone=coordinator.timezone register="registerChild" deregister="deregisterChild"}}{{/date-with-expr}}
+ <div class="form-group">
+ <label for="" class="control-label col-xs-2">Time Zone<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ <select onchange={{action (mut coordinator.timezone) value="target.value"}} name="select-input" class="form-control" data-show-icon="true">
+ {{#each timezoneList as |timezone index|}}
+ <option value={{timezone.value}} selected={{eq timezone.value coordinator.timezone}}>{{timezone.displayName}}</option>
+ {{/each}}
+ </select>
+ {{field-error model=this field='coordinator.timezone' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Configuration</h4>
+ </div>
+ <div class="panel-body handlerPanel">
+ {{#name-value-config configuration=coordinator.workflow.configuration}}{{/name-value-config}}
+ </div>
+ </div>
+ {{#sla-info slaInfo=coordinator.slaInfo register="registerChild" slaEnabled=coordinator.slaEnabled}}{{/sla-info}}
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Data</h4>
+ </div>
+ <div class="panel-body handlerPanel">
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Datasets</h4>
+ <button id="dataset-create-btn" {{action 'createDataset'}} type="button" class="btn btn-default pull-right">
+ <i class="fa fa-plus-circle"></i> Add Dataset
+ </button>
+ </div>
+ <div class="panel-body">
+ <ul class="list-group">
+ {{#each coordinator.datasets as |dataset index|}}
+ <li class="list-group-item">
+ {{dataset.name}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteDataset" index bubbles=false}}></i>
+ </span>
+ <span class="pull-right paddingright10">
+ <i class="fa fa-pencil" title="Edit" {{action "editDataset" index bubbles=false}}></i>
+ </span>
+ </li>
+ {{else}}
+ <li class="list-group-item">No Datasets Configured.</li>
+ {{/each}}
+ </ul>
+ {{#if datasetCreateMode}}
+ {{#dataset-config dataset=currentDataset add="addDataset" cancel="cancelDatasetOperation" createMode=datasetCreateMode}}{{/dataset-config}}
+ {{/if}}
+ {{#if datasetEditMode}}
+ {{#dataset-config dataset=currentDataset update="updateDataset" cancel="cancelDatasetOperation" editMode=datasetEditMode}}{{/dataset-config}}
+ {{/if}}
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Inputs</h4>
+ </div>
+ <div class="panel-body handlerPanel">
+ {{#if coordinator.supportsConditionalDataInput}}
+ <div class="">
+ <label for="" class="control-label col-xs-2">Data Input Type</label>
+ <div class="btn-group">
+ <button {{action 'toggleDataTnput' 'simple'}} type="button" class="btn btn-default {{if (eq coordinator.dataInputType 'simple') 'btn-primary' ''}} scope-btn">
+ Simple
+ </button>
+ <button {{action 'toggleDataTnput' 'logical'}} type="button" class="btn btn-default {{if (eq coordinator.dataInputType 'logical') 'btn-primary' ''}} scope-btn">
+ Conditional
+ </button>
+ </div>
+ </div>
+ {{/if}}
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Datasets</h4>
+ {{#if (eq coordinator.dataInputType 'simple')}}
+ <button id="dataset-create-btn" {{action 'createDataInput'}} type="button" class="btn btn-default pull-right">
+ <i class="fa fa-plus-circle"></i> Add Data Input
+ </button>
+ {{else}}
+ {{#if (not conditionalDataInExists)}}
+ <button id="condition-create-btn" {{action 'createCondition'}} type="button" class="btn btn-default pull-right">
+ <i class="fa fa-plus-circle"></i> Add Condition
+ </button>
+ {{/if}}
+ {{/if}}
+ </div>
+ <div class="panel-body">
+ {{#if (eq coordinator.dataInputType 'simple')}}
+ <ul class="list-group">
+ {{#each coordinator.dataInputs as |data index|}}
+ <li class="list-group-item">
+ {{data.name}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteDataInput" index bubbles=false}}></i>
+ </span>
+ <span class="pull-right paddingright10">
+ <i class="fa fa-pencil" title="Edit" {{action "editDataInput" index bubbles=false}}></i>
+ </span>
+ </li>
+ {{else}}
+ <li class="list-group-item">No Data inputs Configured</li>
+ {{/each}}
+ </ul>
+ {{#if dataInputCreateMode}}
+ {{#data-input-output-config datasets=datasetsForInputs data=currentDataInput type="input" add="addDataInput" cancel="cancelDataInputOperation" createMode=dataInputCreateMode}}{{/data-input-output-config}}
+ {{/if}}
+ {{#if dataInputEditMode}}
+ {{#data-input-output-config datasets=datasetsForInputs data=currentDataInput type="input" update="updateDataInput" cancel="cancelDataInputOperation" editMode=dataInputEditMode}}{{/data-input-output-config}}
+ {{/if}}
+ {{/if}}
+ {{#if (eq coordinator.dataInputType 'logical')}}
+ <ul class="list-groups">
+ {{#if conditionalDataInExists}}
+ <li class="list-group-item">
+ {{#conditional-data-input condition=coordinator.conditionalDataInput datasets=datasetsForInputs isToplevel=true register="registerChild" deregister="deregisterChild"}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteCondition" index bubbles=false}}></i>
+ </span>
+ {{/conditional-data-input}}
+ </li>
+ {{else}}
+ <li class="list-group-item">No Conditional Data Inputs Configured</li>
+ {{/if}}
+ </ul>
+ {{/if}}
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Conditional Inputs</h4>
+ {{#if (not inputLogicExists)}}
+ <button id="condition-create-btn" {{action 'createInputLogic'}} type="button" class="btn btn-default pull-right">
+ <i class="fa fa-plus-circle"></i> Add Condition
+ </button>
+ {{/if}}
+ </div>
+ <div class="panel-body handlerPanel">
+ <ul class="list-group">
+ {{#if inputLogicExists}}
+ <li class="list-group-item">
+ {{#conditional-data-input condition=coordinator.inputLogic datasets=datasetsForInputs isToplevel=true register="registerChild" deregister="deregisterChild"}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteInputLogic" index bubbles=false}}></i>
+ </span>
+ {{/conditional-data-input}}
+ </li>
+ {{else}}
+ <li class="list-group-item">No Conditional Data Inputs Configured</li>
+ {{/if}}
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="panel panel-default">
+ <div class="panel-heading clearfix">
+ <h4 class="panel-title pull-left paddingtop7">Outputs</h4>
+ <button id="dataset-create-btn" {{action 'createDataOutput'}} type="button" class="btn btn-default pull-right">
+ <i class="fa fa-plus-circle"></i> Add Data Output
+ </button>
+ </div>
+ <div class="panel-body">
+ <ul class="list-group">
+ {{#each coordinator.dataOutputs as |data index|}}
+ <li class="list-group-item">
+ {{data.name}}
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteDataOutput" index bubbles=false}}></i>
+ </span>
+ <span class="pull-right paddingright10">
+ <i class="fa fa-pencil" title="Edit" {{action "editDataOutput" index bubbles=false}}></i>
+ </span>
+ </li>
+ {{else}}
+ <li class="list-group-item">No Data Ouputs Configured</li>
+ {{/each}}
+ </ul>
+ {{#if dataOutputCreateMode}}
+ {{#data-input-output-config datasets=datasetsForOutputs data=currentDataOutput type="output" add="addDataOutput" cancel="cancelDataOutputOperation" createMode=dataOutputCreateMode}}{{/data-input-output-config}}
+ {{/if}}
+ {{#if dataOutputEditMode}}
+ {{#data-input-output-config datasets=datasetsForOutputs data=currentDataOutput type="output" update="updateDataOutput" cancel="cancelDataOutputOperation" editMode=dataOutputEditMode}}{{/data-input-output-config}}
+ {{/if}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </form>
+ </div>
+</div>
+{{#if showingFileBrowser}}
+ {{hdfs-browser closeFileBrowser="closeFileBrowser" selectFileCallback=selectFileCallback filePath=filePath}}
+{{/if}}
+{{#if showingJobConfig}}
+ {{job-config type='coord' closeJobConfigs="closeCoordSubmitConfig" jobFilePath=coordinatorFilePath openFileBrowser="openFileBrowser" closeFileBrowser="closeFileBrowser" jobConfigs=coordinatorConfigs}}
+{{/if}}
+{{#if showingResetConfirmation}}
+ {{#confirmation-dialog title="Confirm Coordinator Reset"
+ confirmationMessage="Any unsaved changes may be lost. Do you want to proceed resetting the coordinator ?"
+ okBtnText="Continue" cancelBtnText="Cancel" onOk="resetCoordinator"}}{{/confirmation-dialog}}
+{{/if}}
+{{#if showingPreview}}
+ {{#preview-dialog title="Coordinator XML Preview" previewXml=previewXml}}{{/preview-dialog}}
+{{/if}}
+{{#if showParameterSettings}}
+ {{#workflow-parameters type='coord' closeWorkFlowParam="closeWorkFlowParam" saveWorkFlowParam="saveWorkFlowParam" parameters=parameters}}{{/workflow-parameters}}
+{{/if}}
+{{#if showControlConfig}}
+ <div id="control-dialog" class="modal fade" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">Controls</h4>
+ </div>
+ <div class="modal-body">
+ <div class="panel panel-default">
+ <div class="panel-body handlerPanel form-horizontal">
+ {{#each coordinatorControls as |property|}}
+ {{#named-properties property=property labelWidthClass="col-xs-4" inputWidthClass="col-xs-8"}}{{/named-properties}}
+ {{/each}}
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-primary" data-dismiss="modal" {{action "saveCoordControls"}}>Save</button>
+ <button type="button" class="btn btn-default" data-dismiss="modal" onclick={{action (mut showControlConfig) false}}>Cancel</button>
+ </div>
+ </div>
+ </div>
+ </div>
+{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-job-details.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-job-details.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-job-details.hbs
index 65aed2d..350f873 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-job-details.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/coord-job-details.hbs
@@ -119,7 +119,22 @@
<div role="tabpanel" class="tab-pane" id="jobConfig">
<div class="panel panel-default">
<div class="panel-body preview">
- <pre class="prettyprint">{{model.conf}}</pre>
+ <table class="table table-striped configuration-property-table">
+ <thead>
+ <tr>
+ <th class="propertyName">Name</th>
+ <th class="propertyValue">Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each model.configurationProperties as |configurationProperty|}}
+ <tr>
+ <td class="propertyName">{{configurationProperty.name}}</td>
+ <td class="propertyValue">{{configurationProperty.value}}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
</div>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/credentials-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/credentials-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/credentials-config.hbs
index 129b7df..366920d 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/credentials-config.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/credentials-config.hbs
@@ -18,26 +18,18 @@
<form class="form-horizontal" id="credentials_config">
<div class="panel panel-default">
{{#if (eq mode 'edit')}}
- <div class="panel-heading" id="credential-head" {{action 'togglePanel'}}>
- <span>{{credential.name}}</span><span class="cred-type">({{credential.type}})</span>
- {{#if isOpen}}
- <i class="indicator glyphicon glyphicon-chevron-up pull-right"></i>
- {{else}}
- <i class="indicator glyphicon glyphicon-chevron-down pull-right"></i>
- {{/if}}
- <span class="col-xs-1 pull-right">
- <i class="fa fa-trash-o" title="Delete" {{action "delete" credential.name bubbles=false}}></i>
- </span>
+ <div class="panel-heading" id="credential-head">
+ <span>Edit - {{credential.name}}</span><span class="cred-type">({{credential.type}})</span>
</div>
{{else if (eq mode 'create')}}
- <div class="panel-heading" id="credential-head" {{action 'togglePanel'}}>Create New</div>
+ <div class="panel-heading" id="credential-head">Create New</div>
{{/if}}
- <div class="panel-body handlerPanel collapse panel-collapse">
+ <div class="panel-body">
<div class="form-group">
<label class="control-label col-xs-2">Name<span class="requiredField"> *</span></label>
<div class=" col-xs-4">
{{input class="form-control" type="text" value=credential.name}}
- {{field-error error=errors.credential.name}}
+ {{field-error model=this field='credential.name' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
@@ -48,7 +40,7 @@
<option value={{type.value}} selected={{eq type.value credential.type}}>{{type.displayName}}</option>
{{/each}}
</select>
- {{field-error error=errors.credential.type}}
+ {{field-error model=this field='credential.type' showErrorMessage=showErrorMessage}}
</div>
</div>
{{#if credential.type}}
@@ -56,7 +48,7 @@
<div class="panel-heading">Properties</div>
<div class="panel-body handlerPanel">
{{#each staticProps as |property|}}
- {{#named-properties property=property required=true register="register" labelWidthClass="col-xs-4" inputWidthClass="col-xs-4"}}{{/named-properties}}
+ {{#named-properties property=property unregisterRequired=true required=true unregister="unregister" register="register" labelWidthClass="col-xs-4" inputWidthClass="col-xs-8"}}{{/named-properties}}
{{/each}}
</div>
</div>
@@ -73,11 +65,14 @@
{{#name-value-config configuration=credential register="register"}}{{/name-value-config}}
</div>
</div>
- {{#if (eq mode 'create')}}
- <div class="col-xs-2 pull-right">
- <input class="form-control btn btn-success" type="button" {{action "add"}} value="Add">
+ <div class="col-xs-24 pull-right">
+ <input class="btn btn-default marginright5" type="button" {{action "cancel"}} value="Cancel">
+ {{#if (eq mode 'create')}}
+ <input class="btn btn-primary" type="button" {{action "add"}} value="Add">
+ {{else}}
+ <input class="btn btn-primary" type="button" {{action "add"}} value="Update">
+ {{/if}}
</div>
- {{/if}}
</div>
</div>
</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input-output-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input-output-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input-output-config.hbs
new file mode 100644
index 0000000..2185d0d
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input-output-config.hbs
@@ -0,0 +1,68 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="well">
+ <div class="form-group">
+ <label for="" class="control-label col-xs-2">Name<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ {{input type="text" class="form-control" name="coord-name" value=data.name placeholder="Name"}}
+ {{field-error model=this field='data.name' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ <div class="form-group">
+ <label class="control-label col-xs-2">Dataset<span class="requiredField"> *</span></label>
+ <div class="col-xs-7">
+ <select onchange={{action (mut data.dataset) value="target.value"}} name="select-input" class="form-control" data-show-icon="true">
+ <option value="">Select Dataset</option>
+ {{#each datasets as |dataset index|}}
+ <option value={{dataset.name}} selected={{eq dataset.name data.dataset}}>{{dataset.name}}</option>
+ {{/each}}
+ </select>
+ {{field-error model=this field='data.dataset' showErrorMessage=showErrorMessage}}
+ </div>
+ </div>
+ {{#if (eq type 'input')}}
+ <div class="form-group">
+ <label class="control-label col-xs-2">Instance Type<span class="requiredField"> *</span></label>
+ <div class="col-xs-3">
+ <input type="radio" class="marginright5" name="instanceType" checked={{if (eq data.isList true) 'checked'}} onChange={{action "onInstanceTypeChange" true}}>List of Instances
+ </div>
+ <div class="col-xs-3">
+ <input type="radio" class="marginright5" name="instanceType" checked={{if (eq data.isList false) 'checked'}} onChange={{action "onInstanceTypeChange" false}}>With Start and End
+ </div>
+ </div>
+ {{#if data.isList}}
+ {{#instance-list-config instances=data.instances title="Instance"}}{{/instance-list-config}}
+ {{else}}
+ {{#date-with-expr required=true inputName="start" label="Start" inputPlaceholder="Start Time" dateField=data.start register="registerChild" deregister="deregisterChild"}}{{/date-with-expr}}
+ {{#date-with-expr required=true inputName="end" label="End" inputPlaceholder="End Time" dateField=data.end register="registerChild" deregister="deregisterChild"}}{{/date-with-expr}}
+ {{/if}}
+ {{/if}}
+ {{#if (eq type 'output')}}
+ {{#date-with-expr required=true inputName="instance" label="Instance" inputPlaceholder="Instance" dateField=data.instance register="registerChild" deregister="deregisterChild"}}{{/date-with-expr}}
+ {{/if}}
+ <div class="form-group">
+ <div class="col-xs-7 pull-right">
+ <button id="data-add-btn" {{action 'cancel'}} type="button" class="btn btn-default">Cancel</button>
+ {{#if createMode}}
+ <button id="data-add-btn" {{action 'add'}} type="button" class="btn btn-primary">Save</button>
+ {{else}}
+ <button id="data-update-btn" {{action 'update'}} type="button" class="btn btn-primary"> Update </button>
+ {{/if}}
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input.hbs
new file mode 100644
index 0000000..b09d763
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/data-input.hbs
@@ -0,0 +1,40 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="form-inline">
+ <label class="control-label">Data Input</label>
+ <select onchange={{action (mut dataInput.dataset) value="target.value"}} name="select-input" class="form-control" data-show-icon="true">
+ <option value="">Select Dataset</option>
+ {{#each datasets as |dataset index|}}
+ <option value={{dataset.name}} selected={{eq dataset.name dataInput.dataset}}>{{dataset.name}}</option>
+ {{/each}}
+ </select>
+ {{#if showAdvanced}}
+ {{input type=text class="form-control" value=dataInput.name placeholder="Data Input Name"}}
+ {{input type=text class="form-control" value=dataInput.min placeholder="Mininum Inputs"}}
+ {{input type=text class="form-control" value=dataInput.wait placeholder="Wait Time"}}
+ <button id="data-add-btn" {{action 'hideAdvanced'}} type="button" title="Configure Advanced Options" class="form-control btn btn-default">
+ <i class="fa fa-chevron-left"></i> Advanced
+ </button>
+ {{else}}
+ <button id="data-add-btn" {{action 'showAdvanced'}} type="button" title="Configure Advanced Options" class="form-control btn btn-default">
+ <i class="fa fa-chevron-right"></i> Advanced
+ </button>
+ {{/if}}
+ {{yield}}
+</div>
+{{field-error model=this field='dataInput.dataset' showErrorMessage=showErrorMessage}}
[03/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/named-properties.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/named-properties.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/named-properties.hbs
index 2fa78bc..5750422 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/named-properties.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/named-properties.hbs
@@ -21,6 +21,6 @@
</label>
<div class="{{inputWidthClass}}">
{{input type="text" class="form-control" value=property.value placeholder="value"}}
- {{field-error error=errors.property.value}}
+ {{field-error model=this field='property.value' showErrorMessage=showErrorMessage}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action-info.hbs
new file mode 100644
index 0000000..abc8cba
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action-info.hbs
@@ -0,0 +1,47 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Resource Manager : </b><br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Script : </b><br/>{{hoveredAction.script}}</li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Params : </b>
+ {{#property-value-config action=hoveredAction.params}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action.hbs
index eb38432..d0fe490 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/pig-action.hbs
@@ -26,7 +26,7 @@
<button class="btn btn-primary" type="button" {{action "openFileBrowser" "actionModel.script"}}>Browse</button>
</span>
</div>
- {{#field-error error=errors.actionModel.script}}{{/field-error}}
+ {{field-error model=this field='actionModel.script' showErrorMessage=showErrorMessage}}
</div>
</div>
{{#jobxml-config jobXml=actionModel.jobXml openFileBrowser="openFileBrowser" register="register"}}{{/jobxml-config}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-fs.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-fs.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-fs.hbs
index 9d712bf..c549a26 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-fs.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-fs.hbs
@@ -36,51 +36,7 @@
<input class="form-control btn btn-danger" type="button" {{action "deletePrepare" index}} value="-">
</div>
</div>
- {{#if (eq prep.type "mkdir")}}
- <div class="form-group bottom-margin-zero">
- <label class="control-label col-xs-2">Path</label>
- <div class="col-xs-7">
- <div class="input-group">
- {{input type="text" class="form-control" value=prep.settings.path placeholder="path of the directory"}}
- <span class="input-group-btn">
- <button class="btn btn-primary" type="button" {{action "openFileBrowserForListItem" index "path"}}>Browse</button>
- </span>
- </div>
- </div>
- </div>
- {{#unless prep.settings.path}}
- <div class="form-group bottom-margin-zero">
- <label class="text-danger control-label col-xs-2">
- </label>
- <label class="text-danger control-label col-xs-4 rightAlign">
- Path is mandatory
- </label>
- </div>
- {{/unless}}
- {{/if}}
- {{#if (eq prep.type "delete")}}
- <div class="form-group bottom-margin-zero">
- <label class="control-label col-xs-2">Path</label>
- <div class="col-xs-7">
- <div class="input-group">
- {{input type="text" class="form-control" value=prep.settings.path placeholder="path of the directory"}}
- <span class="input-group-btn">
- <button class="btn btn-primary" type="button" {{action "openFileBrowserForListItem" index "path"}}>Browse</button>
- </span>
- </div>
- </div>
- </div>
- {{#unless prep.settings.path}}
- <div class="form-group bottom-margin-zero">
- <label class="text-danger control-label col-xs-2">
- </label>
- <label class="text-danger control-label col-xs-4 rightAlign">
- Path is mandatory
- </label>
- </div>
- {{/unless}}
- {{/if}}
- {{#if (eq prep.type "touchz")}}
+ {{#if (or (eq prep.type "delete") (eq prep.type "mkdir") (eq prep.type "touchz"))}}
<div class="form-group bottom-margin-zero">
<label class="control-label col-xs-2">Path</label>
<div class="col-xs-7">
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-info.hbs
new file mode 100644
index 0000000..866e6b9
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/prepare-config-info.hbs
@@ -0,0 +1,22 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+{{#each action.prepare as |obj|}}
+ <ul class="list-unstyled">
+ <li>Type : {{obj.type}}, Path : {{obj.path}}</li>
+ </ul>
+{{/each}}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/preview-dialog.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/preview-dialog.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/preview-dialog.hbs
new file mode 100644
index 0000000..943c917
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/preview-dialog.hbs
@@ -0,0 +1,33 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="previewModal" class="modal fade" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">{{title}}</h4>
+ </div>
+ <div class="modal-body">
+ <pre class="preview-xml">{{previewXml}}</pre>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/property-value-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/property-value-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/property-value-config.hbs
new file mode 100644
index 0000000..1cd5b69
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/property-value-config.hbs
@@ -0,0 +1,22 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+{{#each action as |obj|}}
+ <ul class="list-unstyled">
+ <li>{{obj.value}}</li>
+ </ul>
+{{/each}}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/save-wf.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/save-wf.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/save-wf.hbs
new file mode 100644
index 0000000..65bac42
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/save-wf.hbs
@@ -0,0 +1,79 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div class="modal fade" id="configureJob" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">Save Workflow</h4>
+ </div>
+ <div class="modal-body">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ {{#if alertType}}
+ <div id="error" class="alert alert-{{alertType}}">
+ <div>{{alertMessage}}</div>
+ <div>{{alertDetails}}</div>
+ {{#if isStackTraceAvailable}}
+ {{#if isStackTraceVisible}}
+ <a href="#" {{action "hideStackTrace"}}>Hide Log</a>
+ <div id="stackTrace">{{{stackTrace}}}</div>
+ {{/if}}
+ {{#unless isStackTraceVisible}}
+ <a href="#" {{action "showStackTrace"}}>Show Log</a>
+ {{/unless}}
+ {{/if}}
+ </div>
+ {{/if}}
+ <div class="row form-group">
+ <div class="col-xs-3">
+ <label class="control-label" for="{{type}}-path">{{displayName}} path</label><span class="requiredField"> *</span>
+ </div>
+ <div class="col-xs-8">
+ <div class="input-group">
+ {{input class="form-control" type="text" name="{{type}}-path" value=filePath}}
+ <span class="input-group-btn">
+ <button type="button" class="btn btn-primary" {{action "selectFile"}}>Browse</button>
+ </span>
+ </div>
+ {{field-error model=this field='filePath' showErrorMessage=showErrorMessage}}
+ {{input type="checkbox" checked=overwritePath}}Overwrite
+ {{#if overwritePath}}
+ <div class="alert alert-info">
+ Sending overwrite option will replace the existing file in hdfs file system.
+ </div>
+ {{/if}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ {{#if savingInProgress}}
+ {{spin-spinner lines=10 length=10 width=5 radius=10 }}
+ <span class="pull-left">Saving {{displayName}}</span>
+ {{/if}}
+ <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+ <button type="button" class="btn btn-primary" {{action "saveWorkflow"}}>Submit</button>
+ </div>
+ </div>
+ </div>
+</div>
+{{#if showingFileBrowser}}
+{{hdfs-browser closeFileBrowser="closeFileBrowser" selectFileCallback=selectFileCallback filePath=filePath}}
+{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action-info.hbs
new file mode 100644
index 0000000..332852c
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action-info.hbs
@@ -0,0 +1,48 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager :</b> <br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.exec}}<li class="list-group-item"><b>Exec : </b><br/>{{hoveredAction.exec}}</li>{{/if}}
+ {{#if hoveredAction.envVar}}<li class="list-group-item"><b>Env Var : </b>
+ {{#property-value-config action=hoveredAction.envVar}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.captureOutput}}<li class="list-group-item"><b>Capture Output : </b><br/>{{hoveredAction.captureOutput}}</li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.archives}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.args}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action.hbs
index 81d2c52..4673c732 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/shell-action.hbs
@@ -27,7 +27,7 @@
<button class="btn btn-primary" type="button" {{action "openFileBrowser" "actionModel.exec"}}>Browse</button>
</span>
</div>
- {{#field-error error=errors.actionModel.exec}}{{/field-error}}
+ {{field-error model=this field='actionModel.exec' showErrorMessage=showErrorMessage}}
</div>
</div>
@@ -63,7 +63,7 @@
<div class="col-xs-7">
{{input type="text" class="form-control" name="job-tracker" value=actionModel.jobTracker placeholder="Resource Manager"}}
</div>
- {{field-error error=errors.actionModel.jobTracker}}
+ {{field-error model=this field='actionModel.jobTracker' showErrorMessage=showErrorMessage}}
</div>
<div class="form-group">
<label for="inputPassword" class="control-label col-xs-2">Name node</label>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sla-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sla-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sla-info.hbs
index e304f80..28bdf15 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sla-info.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sla-info.hbs
@@ -16,11 +16,11 @@
* limitations under the License.
}}
<div class="panel panel-default">
- <div class="panel-heading" id="sla-accordion" data-toggle="collapse" data-parent="#sla-accordion" data-target="#slaCollapse">
+ <div class="panel-heading" id="sla-accordion" data-toggle="collapse" data-parent="#sla-accordion" data-target="#{{collapseId}}">
SLA <span class="grayed">({{if slaEnabled "Enabled" "Disabled"}})</span>
<i class="indicator glyphicon glyphicon-chevron-down pull-right"></i>
</div>
- <div id="slaCollapse" class="panel-collapse collapse panel-body">
+ <div id="{{collapseId}}" class="panel-collapse collapse panel-body">
<div class="form-group">
<label class="control-label col-xs-2">Enabled</label>
<span class="col-xs-2 paddingtop7">{{input type="checkbox" checked=slaEnabled}}</span>
@@ -28,14 +28,15 @@
<div class="form-group">
<label class="control-label col-xs-2 padding10">Nominal Time<span class="requiredField"> *</span></label>
<div class="col-xs-3 padding10">
- {{input type="text" id="nominalTime" title="Date in UTC Format" class="form-control" value=nominalTime placeholder="Nominal Time"}}
+ {{input type="text" name="nominalTime" title="Date in UTC Format" class="form-control" value=nominalTime placeholder="Nominal Time"}}
+ {{field-error model=this field='nominalTime' showErrorMessage=showErrorMessage}}
</div>
- {{field-error error=errors.nominalTime}}
</div>
<div class="form-group">
<label class="control-label col-xs-2">Should Start</label>
<div class="col-xs-3">
{{input class="form-control" type="text" value=slaInfo.shouldStart.time placeholder="Should Start"}}
+ {{field-error model=this field='slaInfo.shouldStart.time' showErrorMessage=showErrorMessage}}
</div>
<div class="col-xs-2">
<select class="form-control" name="time-unit" title="Time Unit" onchange={{action (mut slaInfo.shouldStart.unit) value="target.value"}}>
@@ -43,14 +44,14 @@
<option value={{timeUnit.value}} selected={{eq timeUnit.value slaInfo.shouldStart.unit}}>{{timeUnit.displayName}}</option>
{{/each}}
</select>
- {{field-error error=errors.shouldStart.unit}}
+ {{field-error model=this field='slaInfo.shouldStart.unit' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
<label class="control-label col-xs-2">Should End<span class="requiredField"> *</span></label>
<div class="col-xs-3">
{{input class="form-control" type="text" value=slaInfo.shouldEnd.time placeholder="Should End"}}
- {{field-error error=errors.shouldEnd.time}}
+ {{field-error model=this field='slaInfo.shouldEnd.time' showErrorMessage=showErrorMessage}}
</div>
<div class="col-xs-2">
<select class="form-control" name="time-unit" title="Time Unit" onchange={{action (mut slaInfo.shouldEnd.unit) value="target.value"}}>
@@ -58,7 +59,7 @@
<option value={{timeUnit.value}} selected={{eq timeUnit.value slaInfo.shouldEnd.unit}}>{{timeUnit.displayName}}</option>
{{/each}}
</select>
- {{field-error error=errors.shouldEnd.unit}}
+ {{field-error model=this field='slaInfo.shouldEnd.unit' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
@@ -72,7 +73,7 @@
<option value={{timeUnit.value}} selected={{eq timeUnit.value slaInfo.maxDuration.unit}}>{{timeUnit.displayName}}</option>
{{/each}}
</select>
- {{field-error error=errors.maxDuration.unit}}
+ {{field-error model=this field='slaInfo.maxDuration.unit' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action-info.hbs
new file mode 100644
index 0000000..1b4274f
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action-info.hbs
@@ -0,0 +1,46 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager : </b><br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.class}}<li class="list-group-item"><b>Class : </b><br/>{{hoveredAction.class}} </li>{{/if}}
+ {{#if hoveredAction.jar}}<li class="list-group-item"><b>Jar : </b><br/>{{hoveredAction.jar}} </li>{{/if}}
+ {{#if hoveredAction.master}}<li class="list-group-item"><b>Master : </b><br/>{{hoveredAction.master}} </li>{{/if}}
+ {{#if hoveredAction.args}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.archives}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action.hbs
index 7472995..52bdad5 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/spark-action.hbs
@@ -22,7 +22,7 @@
<label for="inputPassword" class="control-label col-xs-2">Name<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="spark-name" value=actionModel.sparkName placeholder="Spark Name"}}
- {{#field-error error=errors.actionModel.sparkName}}{{/field-error}}
+ {{field-error model=this field='actionModel.sparkName' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
@@ -35,7 +35,7 @@
<button class="btn btn-primary" type="button" {{action "openFileBrowser" "actionModel.jar"}}>Browse</button>
</span>
</div>
- {{#field-error error=errors.actionModel.jar}}{{/field-error}}
+ {{field-error model=this field='actionModel.jar' showErrorMessage=showErrorMessage}}
</div>
</div>
{{#if isJar}}
@@ -63,7 +63,7 @@
<input type=text placeholder="Custom" disabled={{disableCustomMaster}} value={{customMaster}} onchange={{action (mut actionModel.master) value="target.value"}}>
</div>
</div>
- {{#field-error error=errors.actionModel.master}}{{/field-error}}
+ {{field-error model=this field='actionModel.master' showErrorMessage=showErrorMessage}}
</div>
<div class="form-group">
<label for="inputEmail" class="control-label col-xs-2">Spark Options</label>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sqoop-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sqoop-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sqoop-action-info.hbs
new file mode 100644
index 0000000..eb4c31c
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sqoop-action-info.hbs
@@ -0,0 +1,41 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.nameNode}}<li class="list-group-item"><b>Name Node : </b><br/>{{hoveredAction.nameNode}}</li>{{/if}}
+ {{#if hoveredAction.jobTracker}}<li class="list-group-item"><b>Resource Manager :</b> <br/>{{hoveredAction.jobTracker}} </li>{{/if}}
+ {{#if hoveredAction.command}}<li class="list-group-item"><b>Command : </b><br/>{{hoveredAction.command}}</li>{{/if}}
+ {{#if hoveredAction.jobXml}}<li class="list-group-item"><b>Job xml : </b>
+ {{#property-value-config action=hoveredAction.jobXml}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.archives}}<li class="list-group-item"><b>Archives : </b>
+ {{#property-value-config action=hoveredAction.archives}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.files}}<li class="list-group-item"><b>Files : </b>
+ {{#property-value-config action=hoveredAction.files}}{{/property-value-config}}
+ </li>{{/if}}
+ {{#if hoveredAction.prepare}}<li class="list-group-item"><b>Prepare : </b>
+ {{#prepare-config-info action=hoveredAction}}{{/prepare-config-info}}
+ </li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action-info.hbs
new file mode 100644
index 0000000..3e5c363
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action-info.hbs
@@ -0,0 +1,32 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item">{{info-header hoveredAction=hoveredAction hideNotification="hideNotification"}}</li>
+ {{#if hoveredAction.host}}<li class="list-group-item"><b>Host : </b> <br/>{{hoveredAction.host}} </li>{{/if}}
+ {{#if hoveredAction.host}}<li class="list-group-item"><b>Command : </b><br/>{{hoveredAction.command}} </li>{{/if}}
+ {{#if hoveredAction.host}}<li class="list-group-item"><b>Capture Output : </b> <br/>{{hoveredAction.captureOutput}} </li>{{/if}}
+ {{#if hoveredAction.host}}<li class="list-group-item"><b>Arg : </b> <br/>{{hoveredAction.arg}} </li>{{/if}}
+ {{#if hoveredAction.host}}<li class="list-group-item"><b>Args : </b>
+ {{#property-value-config action=hoveredAction.args}}{{/property-value-config}}
+ </li>{{/if}}
+ </ul>
+</div>
+
+
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action.hbs
index 065e270..ab2ebb2 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/ssh-action.hbs
@@ -22,14 +22,14 @@
<label for="inputEmail" class="control-label col-xs-2">Host<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="host" value=actionModel.host placeholder="localhost"}}
- {{field-error error=errors.actionModel.host}}
+ {{field-error model=this field='actionModel.host' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
<label for="inputEmail" class="control-label col-xs-2">Command<span class="requiredField"> *</span></label>
<div class="col-xs-7">
{{input type="text" class="form-control" name="command" value=actionModel.command placeholder="command"}}
- {{field-error error=errors.actionModel.command}}
+ {{field-error model=this field='actionModel.command' showErrorMessage=showErrorMessage}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow-action-info.hbs
new file mode 100644
index 0000000..8b63c23
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow-action-info.hbs
@@ -0,0 +1,29 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+<div id="notificationWidget" class="">
+ <!--a href="#" class="close " data-dismiss="alert" aria-label="close">×</a-->
+ <ul class="list-group">
+ <li class="list-group-item"><b>The details are</b>
+ <a href="#" class="pull-right" {{action "hideNotification"}}>X</a></li>
+ {{#if hoveredAction.appPath}}<li class="list-group-item"><b>App Path : </b><br/>{{hoveredAction.appPath}}</li>{{/if}}
+ {{#if hoveredAction.propagate-configuration}}<li class="list-group-item"><b>Propagate Configuration : </b><br/>{{hoveredAction.propagate-configuration}}</li>{{/if}}
+ {{#if hoveredAction.configuration.property}}<li class="list-group-item"><b>Configuration : </b>
+ {{#name-value-info action=hoveredAction}}{{/name-value-info}}
+ </li>{{/if}}
+ </ul>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow.hbs
index a1ffaba..2841188 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/sub-workflow.hbs
@@ -27,7 +27,7 @@
<button class="btn btn-primary" type="button" {{action "openFileBrowser" "actionModel.appPath"}}>Browse</button>
</span>
</div>
- {{#field-error error=errors.actionModel.appPath}}{{/field-error}}
+ {{field-error model=this field='actionModel.appPath' showErrorMessage=showErrorMessage}}
</div>
</div>
<div class="form-group">
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/transition-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/transition-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/transition-config.hbs
index 65902b3..fe46446 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/transition-config.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/transition-config.hbs
@@ -18,7 +18,7 @@
<div class="form-group">
<label class="control-label col-xs-2">Error To<span class="requiredField"> *</span></label>
<div class=" col-xs-7">
- <select onchange={{action "onSelectChange" value="target.value"}} name="select-node" class="form-control" data-show-icon="true">
+ <select onchange={{action "errorToHandler" value="target.value"}} name="select-node" class="form-control" data-show-icon="true">
<optgroup label="Kill Nodes"></optgroup>
{{#each killNodes as |node index|}}
<option value={{node.name}} selected={{eq node.name transition.errorNode.name}}>{{node.name}}</option>
@@ -28,13 +28,24 @@
<option value={{node.name}} selected={{eq node.name transition.errorNode.name}}>{{node.name}}</option>
{{/each}}
</select>
- {{field-error error=errors.errorNode.name}}
+ {{#if (eq transition.errorNode.type 'kill')}}
+ <span class="kill-message">{{transition.errorNode.killMessage}}</span>
+ {{/if}}
</div>
</div>
-<div class="form-group margin0">
- <label class="control-label col-xs-2">Ok To</label>
- <div class=" col-xs-7 paddingClass">
- {{okToNode.name}}
+<div class="form-group">
+ <label class="control-label col-xs-2">Ok To<span class="requiredField"> *</span></label>
+ <div class=" col-xs-7">
+ <select onchange={{action "okToHandler" value="target.value"}} name="select-node" class="form-control" data-show-icon="true">
+ {{#each currentNode.validOkToNodes as |node index|}}
+ <option value={{node.name}} selected={{eq node.name transition.okToNode.name}}>{{node.name}}</option>
+ {{/each}}
+ </select>
+ {{#if showWarning}}
+ <span class="ok-to-warning">
+ Changing Ok To transition may result in deletion of intermediate nodes. <span class="undo" {{action 'undoChangeOkTo'}}><u>Undo</u></span>
+ </span>
+ {{/if}}
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/version-settings.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/version-settings.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/version-settings.hbs
index 337ad7d..145f81b 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/version-settings.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/version-settings.hbs
@@ -25,7 +25,7 @@
<div class="modal-body">
<div class="row">
<div class="form-group">
- <label class="control-label col-xs-3"> Workflow Verion</label>
+ <label class="control-label col-xs-3"> Workflow Version</label>
<div class="col-xs-7">
<select onchange={{action (mut currentWorkflowVersion) value="target.value"}} name="select-version" class="form-control">
{{#each workflowSchemaVersions as |version index|}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
index 8670161..7c883af 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-actions.hbs
@@ -19,6 +19,7 @@
<span data-toggle="popover" title="Click on an Action to Insert"></span>
<div id="actions">
<div class="_actions_popup">
+ <div class="clearfix"></div>
<h4>Control Flow Nodes</h4>
<ul class="actions_list_left control_flow">
<li {{action 'addAction' 'fork'}} data-name="fork" data-type="fork" class="dr_action_fork _fork enabled"> <i class="fa fa-sitemap"></i> Fork </li>
@@ -26,6 +27,10 @@
</ul>
<div class="clearfix"></div>
<h4>Action Nodes</h4>
+ {{#if clipboardHasContents}}
+ <div><span class="paste-action">Paste from clipboard</span><span class="btn paste-action-btn" {{action 'pasteNode'}}><i class="fa fa-paste"></i></span></div>
+ {{/if}}
+ <div class="clearfix"></div>
<ul class="actions_list_left actionNodes">
<li {{action 'addAction' 'hive'}} class="dr_action enabled" data-name="Hive" data-type="hive"> <i class="fa fa-server"></i> Hive </li>
<li {{action 'addAction' 'hive2'}} class="dr_action enabled" data-name="Hive" data-type="hive2"> <i class="fa fa-server"></i> Hive2</li>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-config.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-config.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-config.hbs
index 1593165..d425bd0 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-config.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-config.hbs
@@ -35,7 +35,7 @@
{{/if}}
<div class="row form-group">
<div class="col-xs-3">
- <label class="control-label" for="Workflow Path">Workflow Path</label><span class="requiredField"> *</span>
+ <label class="control-label" for="Workflow Path">Workflow Pathdafxg</label><span class="requiredField"> *</span>
</div>
<div class="col-xs-8">
<div class="input-group">
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-credentials.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-credentials.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-credentials.hbs
index d0a2b43..464221f 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-credentials.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-credentials.hbs
@@ -26,14 +26,36 @@
<div class=" panel panel-default">
<div class="panel-heading">Credentials</div>
<div class="panel-body handlerPanel">
- {{#each credentialsList as |credential|}}
- {{#credentials-config showCredentials="showCredentials" delete="deleteCredentials" register="register" credential=credential mode="edit"}}{{/credentials-config}}
- {{else}}
- No Credentials
- {{/each}}
+ <div id="credential-action-bar" class="form-group pull-right">
+ <button id="dataset-create-btn" {{action 'createCredentials'}} type="button" class="btn btn-default">
+ <i class="fa fa-plus-circle"></i> Add
+ </button>
+ </div>
+ <div class="paddingtop10">
+ <ul class="list-group credential-list">
+ {{#each credentialsList as |credential index|}}
+ <li class="list-group-item">
+ {{credential.name}}<span class="cred-type">({{credential.type}})</span>
+ <span class="pull-right">
+ <i class="fa fa-trash-o" title="Delete" {{action "deleteCredentials" index bubbles=false}}></i>
+ </span>
+ <span class="pull-right paddingright10">
+ <i class="fa fa-pencil" title="Edit" {{action "editCredentials" index bubbles=false}}></i>
+ </span>
+ </li>
+ {{else}}
+ <span>No Credentials Configured.</span>
+ {{/each}}
+ </ul>
+ </div>
</div>
</div>
- {{#credentials-config showCredentials="showCredentials" add="addCredentials" mode="create"}}{{/credentials-config}}
+ {{#if createMode}}
+ {{#credentials-config credential=currentCredentials showCredentials="showCredentials" add="addCredentials" mode="create" cancel="cancelCreateMode"}}{{/credentials-config}}
+ {{/if}}
+ {{#if editMode}}
+ {{#credentials-config credential=currentCredentials showCredentials="showCredentials" update="updateCredentials" mode="edit" cancel="cancelEditMode"}}{{/credentials-config}}
+ {{/if}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-action-info.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-action-info.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-action-info.hbs
new file mode 100644
index 0000000..8d1e09c
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-action-info.hbs
@@ -0,0 +1,80 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div id="actionInfo">
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <div class="col-md-12">
+ <div class="col-md-2">Name</div>
+ <div class="col-md-10">{{actionInfo.name}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Type</div>
+ <div class="col-md-10">{{actionInfo.type}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Transition</div>
+ <div class="col-md-10">{{actionInfo.transition}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Start Time</div>
+ <div class="col-md-10">{{actionInfo.startTime}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">End Time</div>
+ <div class="col-md-10">{{actionInfo.endTime}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Status</div>
+ <div class="col-md-10">{{actionInfo.status}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Error Code</div>
+ <div class="col-md-10">{{actionInfo.errorCode}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Error Message</div>
+ <div class="col-md-10">{{actionInfo.errorMessage}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">External ID</div>
+ <div class="col-md-10">{{actionInfo.externalId}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">External Status</div>
+ <div class="col-md-10">{{actionInfo.externalStatus}}</div>
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Console URL</div>
+ {{#unless (eq "-" actionInfo.consoleUrl)}}
+ <div class="col-md-10"><a target="_blank" href="{{actionInfo.consoleUrl}}">{{actionInfo.consoleUrl}}</a></div>
+ {{else}}
+ <div class="col-md-10">{{actionInfo.consoleUrl}}</div>
+ {{/unless}}
+ </div>
+ <div class="col-md-12">
+ <div class="col-md-2">Tracker URI</div>
+ {{#unless (eq "-" actionInfo.trackerUri)}}
+ <div class="col-md-10"><a target="_blank" href="{{actionInfo.trackerUri}}">{{actionInfo.trackerUri}}</a></div>
+ {{else}}
+ <div class="col-md-10">{{actionInfo.trackerUri}}</div>
+ {{/unless}}
+ </div>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-details.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-details.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-details.hbs
index 6465ca8..5b33c41 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-details.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-job-details.hbs
@@ -106,67 +106,11 @@
<li role="presentation"><a href="#actionConf" aria-controls="action-conf" role="tab" data-toggle="tab">Configuration</a></li>
</ul>
<div class="tab-content">
- <div role="tabpanel" class="tab-pane active" id="actionInfo">
- <div class="panel panel-default">
- <div class="panel-body">
- <div class="col-md-12">
- <div class="col-md-2">Name</div>
- <div class="col-md-10">{{model.actionDetails.name}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Type</div>
- <div class="col-md-10">{{model.actionDetails.type}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Transition</div>
- <div class="col-md-10">{{model.actionDetails.transition}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Start Time</div>
- <div class="col-md-10">{{model.actionDetails.startTime}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">End Time</div>
- <div class="col-md-10">{{model.actionDetails.endTime}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Status</div>
- <div class="col-md-10">{{model.actionDetails.status}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Error Code</div>
- <div class="col-md-10">{{model.actionDetails.errorCode}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Error Message</div>
- <div class="col-md-10">{{model.actionDetails.errorMessage}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">External ID</div>
- <div class="col-md-10">{{model.actionDetails.externalId}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">External Status</div>
- <div class="col-md-10">{{model.actionDetails.externalStatus}}</div>
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Console URL</div>
- {{#unless (eq "-" model.actionDetails.consoleUrl)}}
- <div class="col-md-10"><a target="_blank" href="{{model.actionDetails.consoleUrl}}">{{model.actionDetails.consoleUrl}}</a></div>
- {{else}}
- <div class="col-md-10">{{model.actionDetails.consoleUrl}}</div>
- {{/unless}}
- </div>
- <div class="col-md-12">
- <div class="col-md-2">Tracker URI</div>
- {{#unless (eq "-" model.actionDetails.trackerUri)}}
- <div class="col-md-10"><a target="_blank" href="{{model.actionDetails.trackerUri}}">{{model.actionDetails.trackerUri}}</a></div>
- {{else}}
- <div class="col-md-10">{{model.actionDetails.trackerUri}}</div>
- {{/unless}}
- </div>
- </div>
- </div>
+ <div role="tabpanel" class="tab-pane active">
+ {{#if model.actionDetails}}
+ {{#workflow-job-action-info actionInfo=model.actionDetails}}
+ {{/workflow-job-action-info}}
+ {{/if}}
</div>
<div role="tabpanel" class="tab-pane" id="actionConf">
<div class="panel panel-default">
@@ -191,7 +135,22 @@
<div role="tabpanel" class="tab-pane" id="jobConfig">
<div class="panel panel-default">
<div class="panel-body preview">
- <pre class="prettyprint">{{model.conf}}</pre>
+ <table class="table table-striped configuration-property-table">
+ <thead>
+ <tr>
+ <th class="propertyName">Name</th>
+ <th class="propertyValue">Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each model.configurationProperties as |configurationProperty|}}
+ <tr>
+ <td class="propertyName">{{configurationProperty.name}}</td>
+ <td class="propertyValue">{{configurationProperty.value}}</td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
</div>
</div>
</div>
@@ -203,11 +162,11 @@
<div class="panel panel-default">
<div class="panel-body preview">
{{#if model.errorLog}}
- <pre>{{model.errorLog}}</pre>
+ <pre>{{model.errorLog}}</pre>
{{else if model.error}}
- <pre>{{model.errorLog}}</pre>
+ <pre>{{model.errorLog}}</pre>
{{else}}
- {{spin-spinner lines=8 length=5 width=3 radius=5 top=220}}
+ {{spin-spinner lines=8 length=5 width=3 radius=5 top=220}}
{{/if}}
</div>
</div>
@@ -216,11 +175,11 @@
<div class="panel panel-default">
<div class="panel-body preview">
{{#if model.auditLog}}
- <pre>{{model.auditLog}}</pre>
+ <pre>{{model.auditLog}}</pre>
{{else if model.error}}
- <pre>{{model.auditLog}}</pre>
+ <pre>{{model.auditLog}}</pre>
{{else}}
- {{spin-spinner lines=8 length=5 width=3 radius=5 top=220}}
+ {{spin-spinner lines=8 length=5 width=3 radius=5 top=220}}
{{/if}}
</div>
</div>
@@ -228,7 +187,68 @@
<div role="tabpanel" class="tab-pane" id="jobDag">
<div class="panel panel-default">
<div class="panel-body">
- <img src={{dagUrl}} />
+ <!-- <img src={{dagUrl}} /> -->
+ <div class="row">
+ <div class="col-xs-8">
+ <div id="cy" class="cy-panel"></div>
+ </div>
+ <div class="col-xs-4">
+ {{#if model.nodeName}}
+ <div class="panel panel-default">
+ <div class="panel-body">
+ <div class="row">
+ <div class="col-md-4 text-bold">Name</div>
+ <div class="col-md-8">{{model.nodeName}}</div>
+ </div>
+ <div class="row">
+ <div class="col-md-4 text-bold">Type</div>
+ <div class="col-md-8">{{model.nodeType}}</div>
+ </div>
+ {{#if model.actionInfo}}
+ <div class="row">
+ <div class="col-md-4 text-bold">Status</div>
+ <div class="col-md-8">{{model.actionInfo.status}}</div>
+ </div>
+ <div class="row">
+ <div class="col-md-4 text-bold">Start Time</div>
+ <div class="col-md-8">{{model.actionInfo.startTime}}</div>
+ </div>
+ <div class="row">
+ <div class="col-md-4 text-bold">End Time</div>
+ <div class="col-md-8">{{model.actionInfo.endTime}}</div>
+ </div>
+ <div class="row pull-right" {{action 'getActionDetails' model.actionInfo}}>
+ <div class="col-md-12">
+ <a data-toggle="modal" href="#" data-target="#actionDetailsModal">More</a>
+ </div>
+ </div>
+ {{else}}
+ <div class="row">
+ <div class="col-md-4 text-bold">Status</div>
+ <div class="col-md-8">Not Started</div>
+ </div>
+ {{/if}}
+ </div>
+ </div>
+ {{#if model.actionDetails}}
+ <div class="modal fade" role="dialog" id="actionDetailsModal">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">Job Action Details</h4>
+ </div>
+ <div class="modal-body">
+ {{#workflow-job-action-info actionInfo=model.actionDetails}}
+ {{/workflow-job-action-info}}
+ </div>
+ </div>
+ </div>
+ </div>
+ {{/if}}
+ {{/if}}
+ </div>
+ </div>
</div>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-node.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-node.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-node.hbs
index e80462c..6187b27 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-node.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-node.hbs
@@ -53,9 +53,10 @@
<div class="node_actions node_left">
<i class="fa fa-cog node_properties" title="Edit" {{action "openEditor"}}></i>
<i class="fa fa-trash-o" title="Delete" {{action "deleteNode"}}></i>
+ <i class="fa fa-copy" title="Copy" {{action "copyNode"}}></i>
</div>
<div class="action_node_data">
- <i class="fa fa-{{icon}}"></i>
+ <i class="fa fa-{{icon}}" {{action "showNotification" node on="mouseEnter"}}></i>
{{input required pattern="([a-zA-Z_]([\-_a-zA-Z0-9])*){1,39}" name="actionName" data-toggle="tooltip" title=node.name classBinding="node.errors:error:editable" class="editable" value=node.name placeholder="Action Name"}}
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-parameters.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-parameters.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-parameters.hbs
index 769db30..b097af2 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-parameters.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/components/workflow-parameters.hbs
@@ -20,24 +20,23 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
- <h4 class="modal-title">Workflow Parameters</h4>
+ <h4 class="modal-title">{{displayName}} Parameters</h4>
</div>
<div class="modal-body">
-
- <div class=" panel panel-default">
- <div class="panel-heading">Configuration</div>
- <div class="panel-body handlerPanel">
- {{#field-error error=errors.parameters}}{{/field-error}}
- <form class="form-horizontal" id="action_properties">
- {{#name-value-config configuration=parameters.configuration register="register"}}{{/name-value-config}}
- </form>
+ <div class=" panel panel-default">
+ <div class="panel-heading">Configuration</div>
+ <div class="panel-body handlerPanel">
+ {{field-error model=this field='parameters.configuration.property' showErrorMessage=showErrorMessage}}
+ <form class="form-horizontal" id="action_properties">
+ {{#name-value-config configuration=parameters.configuration validations=validations register="register"}}{{/name-value-config}}
+ </form>
+ </div>
</div>
</div>
- </div>
<div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
+ <button type="button" class="btn btn-default" data-dismiss="modal" {{action 'close'}}>Cancel</button>
<button type="button" class="btn btn-primary" {{action "saveParameters"}}>Save</button>
</div>
</div>
</div>
-</div>
\ No newline at end of file
+</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/dashboard.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/dashboard.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/dashboard.hbs
index b580720..41a23b1 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/dashboard.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/dashboard.hbs
@@ -24,7 +24,7 @@
<span class="navbar-brand">Workflow Dashboard</span>
<div class="navbar-brand" id="create-new-button">
<button type="button" {{action "launchDesign"}} class="btn btn-default whiteLabel">
- <i class="fa fa-sitemap"></i> Create Workflow
+ <i class="fa fa-sitemap marginright5"></i>Workflow Designer
</button>
{{help-icon}}
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/templates/design.hbs
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/templates/design.hbs b/contrib/views/wfmanager/src/main/resources/ui/app/templates/design.hbs
index b020c86..cb0462c 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/templates/design.hbs
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/templates/design.hbs
@@ -15,4 +15,4 @@
* See the License for the specific language governing permissions and
* limitations under the License.
}}
-{{flow-designer xmlAppPath=appPath}}
+{{designer-workspace xmlAppPath=xmlAppPath}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js b/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
index d9ca912..2f7df82 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/utils/constants.js
@@ -17,6 +17,9 @@
import Ember from 'ember';
export default Ember.Object.create({
+ Workflow : 'wf',
+ Coordinator : 'coord',
+ Bundle : 'bundle',
globalSetting:{
useJoinNodeForDecision:false,
useAdditionalPlaceholderFlowForDecision:true,
@@ -27,6 +30,9 @@ export default Ember.Object.create({
showErrorTransitions:false,
generatedByCdata: "Generated by Worflow Designer",
rmDefaultValue: "${resourceManager}",
+ defaultNameNodeValue : "${nameNode}",
+ useCytoscape : true,
+ autoRestoreWorkflowEnabled : true,
actions:{
hiveAction:{name : "hive",supportsSchema : true, currentVersion:''},
hive2Action:{name : "hive2",supportsSchema : true, currentVersion:''},
@@ -43,5 +49,40 @@ export default Ember.Object.create({
},
sparkMasterList :Ember.A([{value:'yarn-cluster',displayName:'Yarn Cluster'},
{value:'yarn-client',displayName:'Yarn Client'},
- {value:'local',displayName:'Local'}])
+ {value:'local',displayName:'Local'}]),
+ timezoneList : Ember.A([
+ {displayName:'UTC',gmtOffset:0, value:'UTC'},
+ {displayName:'(GMT -12:00) Eniwetok, Kwajalein',gmtOffset:12, value:'GMT-12:00'},
+ {displayName:'(GMT -11:00) Midway Island, Samoa',gmtOffset:11, value:'GMT-11:00'},
+ {displayName:'(GMT -10:00) Hawaii',gmtOffset:10, value:'GMT-10:00'},
+ {displayName:'(GMT -9:00) Alaska',gmtOffset:9, value:'GMT-09:00'},
+ {displayName:'(GMT -8:00) Pacific Time (US & Canada)',gmtOffset:8, value:'GMT-08:00'},
+ {displayName:'(GMT -7:00) Mountain Time (US & Canada)',gmtOffset:7, value:'GMT-07:00'},
+ {displayName:'(GMT -6:00) Central Time (US & Canada), Mexico City',gmtOffset:6, value:'GMT-06:00'},
+ {displayName:'(GMT -5:00) Eastern Time (US & Canada), Bogota, Lima',gmtOffset:5, value:'GMT-05:00'},
+ {displayName:'(GMT -4:00) Atlantic Time (Canada), Caracas, La Paz',gmtOffset:4, value:'GMT-04:00'},
+ {displayName:'(GMT -3:30) Newfoundland',gmtOffset:3.5, value:'GMT-03:30'},
+ {displayName:'(GMT -3:00) Brazil, Buenos Aires, Georgetown',gmtOffset:3, value:'GMT-03:00'},
+ {displayName:'(GMT -2:00) Mid-Atlantic',gmtOffset:2, value:'GMT-02:00'},
+ {displayName:'(GMT -1:00 hour) Azores, Cape Verde Islands',gmtOffset:1, value:'GMT-01:00'},
+ {displayName:'(GMT) Western Europe Time, London, Lisbon, Casablanca',gmtOffset:0, value:'GMT+00:00'},
+ {displayName:'(GMT +1:00 hour) Brussels, Copenhagen, Madrid, Paris',gmtOffset:-1, value:'GMT+01:00'},
+ {displayName:'(GMT +2:00) Kaliningrad, South Africa',gmtOffset:-2, value:'GMT+02:00'},
+ {displayName:'(GMT +3:00) Baghdad, Riyadh, Moscow, St. Petersburg',gmtOffset:-3, value:'GMT+03:00'},
+ {displayName:'(GMT +3:30) Tehran',gmtOffset:-3.5, value:'GMT+03:30'},
+ {displayName:'(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi',gmtOffset:-4, value:'GMT+04:00'},
+ {displayName:'(GMT +4:30) Kabul',gmtOffset:-4.5, value:'GMT+04:30'},
+ {displayName:'(GMT +5:00) Ekaterinburg, Islamabad, Karachi, Tashkent',gmtOffset:-5, value:'GMT+05:00'},
+ {displayName:'(GMT +5:30) Bombay, Calcutta, Madras, New Delhi',gmtOffset:-5.5,value:'GMT+05:30'},
+ {displayName:'(GMT +5:45) Kathmandu',gmtOffset:-5.75, value:'GMT+05:45'},
+ {displayName:'(GMT +6:00) Almaty, Dhaka, Colombo',gmtOffset:-6, value:'GMT+06:00'},
+ {displayName:'(GMT +7:00) Bangkok, Hanoi, Jakarta',gmtOffset:-7, value:'GMT+07:00'},
+ {displayName:'(GMT +8:00) Beijing, Perth, Singapore, Hong Kong',gmtOffset:-8, value:'GMT+08:00'},
+ {displayName:'(GMT +9:00) Tokyo, Seoul, Osaka, Sapporo, Yakutsk',gmtOffset:-9, value:'GMT+09:00'},
+ {displayName:'(GMT +9:30) Adelaide, Darwin',gmtOffset:-9.5, value:'GMT+09:30'},
+ {displayName:'(GMT +10:00) Eastern Australia, Guam, Vladivostok',gmtOffset:-10, value:'GMT+10:00'},
+ {displayName:'(GMT +11:00) Magadan, Solomon Islands, New Caledonia',gmtOffset:-11, value:'GMT+11:00'},
+ {displayName:'(GMT +12:00) Auckland, Wellington, Fiji, Kamchatka',gmtOffset:-12, value:'GMT+12:00'}
+ ]),
+ persistWorkInProgressInterval : 30000,
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/decission-node-validator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/decission-node-validator.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/decission-node-validator.js
new file mode 100644
index 0000000..4d2c53e
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/decission-node-validator.js
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const DecissionNodeValidator = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ var hasDefaultCond = false;
+ value.forEach(function(item){
+ if(item.condition === "default"){
+ hasDefaultCond = true;
+ return;
+ }
+ });
+ if(!hasDefaultCond){
+ return "Decision Should have one default condition";
+ }
+ var hasEmptyCond = false;
+ value.forEach(function(item){
+ if(item.condition === '' || item.condition === undefined || Ember.$.trim(item.condition).length === 0){
+ hasEmptyCond = true;
+ return;
+ }
+ });
+ if(hasEmptyCond){
+ return "Condition cannot be blank";
+ }
+ return true;
+ }
+});
+
+DecissionNodeValidator.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default DecissionNodeValidator;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-data-node-name.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-data-node-name.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-data-node-name.js
new file mode 100644
index 0000000..5282544
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-data-node-name.js
@@ -0,0 +1,60 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import Ember from 'ember';
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const DuplicateDataNodeName = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ if (model.get('dataNodes')) {
+ var nodeNames = new Map();
+ model.get("validationErrors").clear();
+ model.get('dataNodes').forEach((item)=>{
+ if (item.data.node && item.data.node.name) {
+ Ember.set(item.data.node, "errors", false);
+ if(nodeNames.get(item.data.node.name)){
+ Ember.set(item.data.node, "errors", true);
+ model.get("validationErrors").pushObject({node:item.data,message:"Node name should be unique"});
+ }else{
+ nodeNames.set(item.data.node.name, item.data);
+ Ember.set(item.data.node, "errors", false);
+ }
+ }
+ });
+
+ if(model.get('dataNodes').length !== nodeNames.size){
+ return false;
+ }
+ return true;
+ }
+ return true;
+ }
+});
+
+DuplicateDataNodeName.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default DuplicateDataNodeName;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-flattened-node-name.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-flattened-node-name.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-flattened-node-name.js
new file mode 100644
index 0000000..046cb53
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-flattened-node-name.js
@@ -0,0 +1,66 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import Ember from 'ember';
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const DuplicateFlattenedNodeName = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ var nodeNames = new Map();
+ model.get("validationErrors").clear();
+ model.get('flattenedNodes').forEach((item)=>{
+ Ember.set(item, "errors", false);
+ if(nodeNames.get(item.name)){
+ Ember.set(item, "errors", true);
+ model.get("validationErrors").pushObject({node:item,message:"Node name should be unique"});
+ }else{
+ nodeNames.set(item.name, item);
+ Ember.set(item, "errors", false);
+ }
+ if(model.get("supportedActionTypes").indexOf(item.actionType) === -1 && item.type === "action"){
+ model.get('validationErrors').pushObject({node : item ,message : item.actionType+" is unsupported"});
+ }
+ var nodeErrors=item.validateCustom();
+ if (nodeErrors.length>0){
+ Ember.set(item, "errors", true);
+ nodeErrors.forEach(function(errMsg){
+ model.get("errors").pushObject({node:item,message:errMsg });
+ });
+ }
+ });
+
+ if(model.get('flattenedNodes').length !== nodeNames.size || (model.get("errors") && model.get("errors").length>0)){
+ return false;
+ }
+ return true;
+ }
+});
+
+DuplicateFlattenedNodeName.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default DuplicateFlattenedNodeName;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-kill-node-name.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-kill-node-name.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-kill-node-name.js
new file mode 100644
index 0000000..b8770c2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/duplicate-kill-node-name.js
@@ -0,0 +1,58 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const DuplicateKillNodeName = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ let killNodes = [], flag;
+ model.get("validationErrors").clear();
+ if(model.get("workflow") && model.get("workflow").killNodes){
+ killNodes = model.get("workflow").killNodes;
+ for(let i=0; i<killNodes.length; i++){
+ for(let j=0; j<killNodes.length; j++){
+ if(killNodes[i].name === killNodes[j].name && i !== j){
+ model.get('validationErrors').pushObject({node : killNodes[j] ,message : "Duplicate killnode"});
+ flag = true;
+ break;
+ }
+ }
+ if(flag){
+ break;
+ }
+ }
+ }
+ if (flag){
+ return false;
+ }
+ return true;
+ }
+});
+
+DuplicateKillNodeName.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default DuplicateKillNodeName;
[02/10] ambari git commit: AMBARI-18691. Improve and Update Workflow
designer to support coordinators and bundles. (Belliraj HB via dipayanb)
Posted by db...@apache.org.
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/fs-action-validator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/fs-action-validator.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/fs-action-validator.js
new file mode 100644
index 0000000..4064379
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/fs-action-validator.js
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const FsActionValidator = BaseValidator.extend({
+ validate(value, options, model, attribute/**/) {
+ var isValidated = true,
+ msg = "";
+ if (!value.length) {
+ return false;
+ }
+ value.forEach(function(item) {
+ switch (item.type) {
+ case "mkdir":
+ case "delete":
+ case "touchz":
+ if (!item.settings.path) {
+ isValidated = false;
+ msg = "path is mandatory";
+ }
+ break;
+ case "chmod":
+ if (!item.settings.path) {
+ isValidated = false;
+ msg = "path and permissions are mandatory";
+ }
+ break;
+ case "chgrp":
+ if (!item.settings.path || !item.settings.group) {
+ isValidated = false;
+ msg = "path and group are mandatory";
+ }
+ break;
+ case "move":
+ if (!item.settings.source || !item.settings.target) {
+ isValidated = false;
+ msg = "source and target are mandatory";
+ }
+ break;
+ }
+ });
+ if (msg.length) {
+ return false;
+ }
+ return true;
+ }
+});
+
+FsActionValidator.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default FsActionValidator;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/job-params-validator.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/job-params-validator.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/job-params-validator.js
new file mode 100644
index 0000000..9940bd7
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/job-params-validator.js
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const JobParamsValidator = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ if(!value || value.length === 0){
+ return true;
+ }
+ var missingConfig = false;
+ value.forEach(function(item) {
+ if (item.isRequired && (!item || !item.value || item.value==="")){
+ missingConfig = true;
+ return;
+ }else if(!item.isRequired && (!item || !item.value || item.value==="")){
+ return;
+ }
+ });
+ if(missingConfig){
+ return "You need to fill all the mandatory job properties";
+ }
+ return true;
+
+ }
+});
+
+JobParamsValidator.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default JobParamsValidator;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/operand-length.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/operand-length.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/operand-length.js
new file mode 100644
index 0000000..b79596b
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/operand-length.js
@@ -0,0 +1,46 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const OperandLength = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ if (options.min && value && value.length >= options.min) {
+ return true;
+ }else{
+ if(options.message){
+ return options.message;
+ }
+ return "Atleast two inputs are required";
+ }
+ }
+});
+
+OperandLength.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default OperandLength;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/app/validators/unique-name.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/validators/unique-name.js b/contrib/views/wfmanager/src/main/resources/ui/app/validators/unique-name.js
new file mode 100644
index 0000000..c08dc09
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/validators/unique-name.js
@@ -0,0 +1,59 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import BaseValidator from 'ember-cp-validations/validators/base';
+
+const UniqueName = BaseValidator.extend({
+ validate(value, options, model, attribute) {
+ var nameMap = [], errorMsg = undefined, i = 0;
+ if(value){
+ value.forEach(function(item, index){
+ if(!item.name){
+ errorMsg = "Name cannot be blank";
+ i = index;
+ } else if(nameMap.indexOf(item.name) > -1){
+ i = index;
+ errorMsg = "Name cannot be duplicate";
+ } else{
+ nameMap.push(item.name);
+ }
+ });
+ if(errorMsg){
+ if(i){
+ value.splice(i, 1);
+ }
+ return errorMsg;
+ }
+ return true;
+ }
+ }
+});
+
+UniqueName.reopenClass({
+ /**
+ * Define attribute specific dependent keys for your validator
+ *
+ * @param {String} attribute The attribute being evaluated
+ * @param {Unknown} options Options passed into your validator
+ * @return {Array}
+ */
+ getDependentsFor(/* attribute, options */) {
+ return [];
+ }
+});
+
+export default UniqueName;
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/bower.json
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/bower.json b/contrib/views/wfmanager/src/main/resources/ui/bower.json
index cbab954..0d897f1 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/bower.json
+++ b/contrib/views/wfmanager/src/main/resources/ui/bower.json
@@ -22,6 +22,9 @@
"abdmob/x2js": "~1.2.0",
"bootstrap-treeview": "~1.2.0",
"datatables": "~1.10.11",
- "vkBeautify": "https://github.com/vkiryukhin/vkBeautify.git"
+ "vkBeautify": "https://github.com/vkiryukhin/vkBeautify.git",
+ "cytoscape": "^2.7.7",
+ "cytoscape-dagre": "^1.3.0",
+ "cytoscape-panzoom": "^2.4.0"
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js b/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
index 063c332..5f8b81c 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
+++ b/contrib/views/wfmanager/src/main/resources/ui/ember-cli-build.js
@@ -107,6 +107,16 @@ module.exports = function(defaults) {
//vkBeautify
app.import('bower_components/vkBeautify/vkbeautify.js')
+
+ //cytoscape
+ app.import('bower_components/cytoscape/dist/cytoscape.js');
+
+ //cytoscape-dagre
+ app.import('bower_components/cytoscape-dagre/cytoscape-dagre.js');
+
+ //cytoscape-panzoom
+ app.import('bower_components/cytoscape-panzoom/cytoscape-panzoom.js');
+ app.import('bower_components/cytoscape-panzoom/cytoscape.js-panzoom.css');
return app.toTree();
};
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/addon/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/addon/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/addon/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/app/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/app/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/app/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/components/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/components/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/components/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/controllers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/controllers/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/controllers/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/helpers/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/helpers/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/helpers/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/models/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/models/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/models/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/routes/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/routes/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/routes/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/templates/components/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/templates/components/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/dummy/app/templates/components/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/integration/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/integration/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/integration/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/unit/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/unit/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/tests/unit/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/vendor/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/vendor/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/externaladdons/hdfs-directory-viewer/vendor/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/mock-service/mock-server.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/mock-service/mock-server.js b/contrib/views/wfmanager/src/main/resources/ui/mock-service/mock-server.js
new file mode 100644
index 0000000..f8a40ab
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/mock-service/mock-server.js
@@ -0,0 +1,52 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ "use strict";
+
+ var bodyParser = require('body-parser'),
+ express = require('express'),
+ mockData = require('./mockData.js'),
+ server = express(),
+ PORT = process.env.PORT || 11000;
+
+ server.use('/', express.static(__dirname + '/dist'));
+ server.use(bodyParser());
+ server.use(function (req, res, next) {
+ if (req.is('text/*')) {
+ req.text = '';
+ req.setEncoding('utf8');
+ req.on('data', function (chunk) { req.text += chunk; });
+ req.on('end', next);
+ } else {
+ next();
+ }
+ });
+
+ server.get('/oozie/v2/jobs', function(req, res) {
+ res.json(200, mockData.getJobs());
+ });
+
+ server.get('/oozie/v2/job/:id', function(req, res) {
+ res.json(200, mockData.getJobById());
+ });
+
+ server.listen(PORT, function () {
+ console.log('Dev server listening on port ' + PORT);
+ });
+
+}());
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/mock-service/mockData.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/mock-service/mockData.js b/contrib/views/wfmanager/src/main/resources/ui/mock-service/mockData.js
new file mode 100644
index 0000000..7eb3ebb
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/mock-service/mockData.js
@@ -0,0 +1,316 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ function getJobs(){
+ return jobs;
+ };
+
+ function getJobById(id){
+ /* jobs.find(function(job){
+ return job.id == id;
+ });*/
+ return jobDetail;
+ }
+
+ var jobs = {
+ "total":1127,
+ "workflows":[
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"FAILED",
+ "createdTime":"Mon, 18 Jul 2016 17:18:19 GMT",
+ "conf":null,
+ "lastModTime":"Mon, 18 Jul 2016 17:18:27 GMT",
+ "run":0,
+ "endTime":"Mon, 18 Jul 2016 17:18:27 GMT",
+ "externalId":"0001250-160321130408525-oozie-oozi-W@user-action@0",
+ "appName":"falcon-dr-hive-workflow",
+ "id":"0001251-160321130408525-oozie-oozi-W",
+ "startTime":"Mon, 18 Jul 2016 17:18:19 GMT",
+ "parentId":"0001250-160321130408525-oozie-oozi-W",
+ "toString":"Workflow id[0001251-160321130408525-oozie-oozi-W] status[FAILED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001251-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"KILLED",
+ "createdTime":"Mon, 18 Jul 2016 17:18:06 GMT",
+ "conf":null,
+ "lastModTime":"Tue, 19 Jul 2016 17:18:17 GMT",
+ "run":0,
+ "endTime":"Tue, 19 Jul 2016 17:18:17 GMT",
+ "externalId":"hiveMirror11463038709928\/DEFAULT\/2016-05-19T16:02Z",
+ "appName":"FALCON_PROCESS_DEFAULT_hiveMirror11463038709928",
+ "id":"0001250-160321130408525-oozie-oozi-W",
+ "startTime":"Mon, 18 Jul 2016 17:18:07 GMT",
+ "parentId":"0000735-160321130408525-oozie-oozi-C@2077",
+ "toString":"Workflow id[0001250-160321130408525-oozie-oozi-W] status[KILLED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001250-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"FAILED",
+ "createdTime":"Thu, 19 May 2016 16:01:47 GMT",
+ "conf":null,
+ "lastModTime":"Thu, 19 May 2016 16:01:50 GMT",
+ "run":0,
+ "endTime":"Thu, 19 May 2016 16:01:50 GMT",
+ "externalId":"0001248-160321130408525-oozie-oozi-W@user-action@0",
+ "appName":"falcon-dr-hive-workflow",
+ "id":"0001249-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 16:01:47 GMT",
+ "parentId":"0001248-160321130408525-oozie-oozi-W",
+ "toString":"Workflow id[0001249-160321130408525-oozie-oozi-W] status[FAILED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001249-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"KILLED",
+ "createdTime":"Thu, 19 May 2016 16:01:43 GMT",
+ "conf":null,
+ "lastModTime":"Tue, 19 Jul 2016 17:18:16 GMT",
+ "run":0,
+ "endTime":"Tue, 19 Jul 2016 17:18:15 GMT",
+ "externalId":"hiveMirror11463038709928\/DEFAULT\/2016-05-19T15:57Z",
+ "appName":"FALCON_PROCESS_DEFAULT_hiveMirror11463038709928",
+ "id":"0001248-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 16:01:43 GMT",
+ "parentId":"0000735-160321130408525-oozie-oozi-C@2076",
+ "toString":"Workflow id[0001248-160321130408525-oozie-oozi-W] status[KILLED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001248-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"FAILED",
+ "createdTime":"Thu, 19 May 2016 15:56:47 GMT",
+ "conf":null,
+ "lastModTime":"Thu, 19 May 2016 15:56:48 GMT",
+ "run":0,
+ "endTime":"Thu, 19 May 2016 15:56:48 GMT",
+ "externalId":"0001246-160321130408525-oozie-oozi-W@user-action@0",
+ "appName":"falcon-dr-hive-workflow",
+ "id":"0001247-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 15:56:47 GMT",
+ "parentId":"0001246-160321130408525-oozie-oozi-W",
+ "toString":"Workflow id[0001247-160321130408525-oozie-oozi-W] status[FAILED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001247-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"KILLED",
+ "createdTime":"Thu, 19 May 2016 15:56:45 GMT",
+ "conf":null,
+ "lastModTime":"Tue, 19 Jul 2016 17:18:15 GMT",
+ "run":0,
+ "endTime":"Tue, 19 Jul 2016 17:18:15 GMT",
+ "externalId":"hiveMirror11463038709928\/DEFAULT\/2016-05-19T15:52Z",
+ "appName":"FALCON_PROCESS_DEFAULT_hiveMirror11463038709928",
+ "id":"0001246-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 15:56:45 GMT",
+ "parentId":"0000735-160321130408525-oozie-oozi-C@2075",
+ "toString":"Workflow id[0001246-160321130408525-oozie-oozi-W] status[KILLED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001246-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"FAILED",
+ "createdTime":"Thu, 19 May 2016 13:12:02 GMT",
+ "conf":null,
+ "lastModTime":"Thu, 19 May 2016 13:12:03 GMT",
+ "run":0,
+ "endTime":"Thu, 19 May 2016 13:12:03 GMT",
+ "externalId":"0001244-160321130408525-oozie-oozi-W@user-action@0",
+ "appName":"falcon-dr-hive-workflow",
+ "id":"0001245-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 13:12:02 GMT",
+ "parentId":"0001244-160321130408525-oozie-oozi-W",
+ "toString":"Workflow id[0001245-160321130408525-oozie-oozi-W] status[FAILED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001245-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"KILLED",
+ "createdTime":"Thu, 19 May 2016 13:12:00 GMT",
+ "conf":null,
+ "lastModTime":"Tue, 19 Jul 2016 17:18:17 GMT",
+ "run":0,
+ "endTime":"Tue, 19 Jul 2016 17:18:17 GMT",
+ "externalId":"hiveMirror11463038709928\/DEFAULT\/2016-05-19T13:12Z",
+ "appName":"FALCON_PROCESS_DEFAULT_hiveMirror11463038709928",
+ "id":"0001244-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 13:12:01 GMT",
+ "parentId":"0000735-160321130408525-oozie-oozi-C@2043",
+ "toString":"Workflow id[0001244-160321130408525-oozie-oozi-W] status[KILLED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001244-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"FAILED",
+ "createdTime":"Thu, 19 May 2016 13:07:02 GMT",
+ "conf":null,
+ "lastModTime":"Thu, 19 May 2016 13:07:03 GMT",
+ "run":0,
+ "endTime":"Thu, 19 May 2016 13:07:03 GMT",
+ "externalId":"0001242-160321130408525-oozie-oozi-W@user-action@0",
+ "appName":"falcon-dr-hive-workflow",
+ "id":"0001243-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 13:07:02 GMT",
+ "parentId":"0001242-160321130408525-oozie-oozi-W",
+ "toString":"Workflow id[0001243-160321130408525-oozie-oozi-W] status[FAILED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001243-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"KILLED",
+ "createdTime":"Thu, 19 May 2016 13:07:01 GMT",
+ "conf":null,
+ "lastModTime":"Tue, 19 Jul 2016 17:18:16 GMT",
+ "run":0,
+ "endTime":"Tue, 19 Jul 2016 17:18:16 GMT",
+ "externalId":"hiveMirror11463038709928\/DEFAULT\/2016-05-19T13:07Z",
+ "appName":"FALCON_PROCESS_DEFAULT_hiveMirror11463038709928",
+ "id":"0001242-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 13:07:01 GMT",
+ "parentId":"0000735-160321130408525-oozie-oozi-C@2042",
+ "toString":"Workflow id[0001242-160321130408525-oozie-oozi-W] status[KILLED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001242-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"FAILED",
+ "createdTime":"Thu, 19 May 2016 13:02:02 GMT",
+ "conf":null,
+ "lastModTime":"Thu, 19 May 2016 13:02:03 GMT",
+ "run":0,
+ "endTime":"Thu, 19 May 2016 13:02:03 GMT",
+ "externalId":"0001240-160321130408525-oozie-oozi-W@user-action@0",
+ "appName":"falcon-dr-hive-workflow",
+ "id":"0001241-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 13:02:02 GMT",
+ "parentId":"0001240-160321130408525-oozie-oozi-W",
+ "toString":"Workflow id[0001241-160321130408525-oozie-oozi-W] status[FAILED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001241-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ },
+ {
+ "appPath":null,
+ "acl":null,
+ "status":"KILLED",
+ "createdTime":"Thu, 19 May 2016 13:02:00 GMT",
+ "conf":null,
+ "lastModTime":"Tue, 19 Jul 2016 17:18:15 GMT",
+ "run":0,
+ "endTime":"Tue, 19 Jul 2016 17:18:15 GMT",
+ "externalId":"hiveMirror11463038709928\/DEFAULT\/2016-05-19T13:02Z",
+ "appName":"FALCON_PROCESS_DEFAULT_hiveMirror11463038709928",
+ "id":"0001240-160321130408525-oozie-oozi-W",
+ "startTime":"Thu, 19 May 2016 13:02:00 GMT",
+ "parentId":"0000735-160321130408525-oozie-oozi-C@2041",
+ "toString":"Workflow id[0001240-160321130408525-oozie-oozi-W] status[KILLED]",
+ "group":null,
+ "consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001240-160321130408525-oozie-oozi-W",
+ "user":"root",
+ "actions":[
+
+ ]
+ }
+ ],
+ "len":12,
+ "offset":1
+}
+
+
+var jobDetail = {"appPath":"hdfs:\/\/sandbox.hortonworks.com:8020\/tmp\/extensions\/hive-mirroring\/resources\/runtime\/hive-mirroring-workflow.xml","acl":null,"status":"FAILED","createdTime":"Mon, 18 Jul 2016 17:18:19 GMT","conf":"<configuration>\r\n <property>\r\n <name>falconInputNames<\/name>\r\n <value>NONE<\/value>\r\n <\/property>\r\n <property>\r\n <name>mapreduce.job.user.name<\/name>\r\n <value>root<\/value>\r\n <\/property>\r\n <property>\r\n <name>distcpMapBandwidth<\/name>\r\n <value>100<\/value>\r\n <\/property>\r\n <property>\r\n <name>falconInPaths<\/name>\r\n <value>NONE<\/value>\r\n <\/property>\r\n <property>\r\n <name>feedNames<\/name>\r\n <value>NONE<\/value>\r\n <\/property>\r\n <property>\r\n <name>falcon.libpath<\/name>\r\n <value>\/apps\/falcon\/primaryCluster\/working\/lib<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.wf.application.lib<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020
\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-client-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-common-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-distcp-replication-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-extensions-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/
hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-feed-lifecycle-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-hadoop-dependencies-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-hive-replication-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-messaging-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5
360b176_1463394572377\/DEFAULT\/lib\/falcon-metrics-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-oozie-adaptor-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-prism-0.9.2.5.0.0-357-classes.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-rerun-0.9.2.5.0.0-357.jar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-retention-0.9.2.5.0.0-357.j
ar,hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib\/falcon-scheduler-0.9.2.5.0.0-357.jar<\/value>\r\n <\/property>\r\n <property>\r\n <name>sourceTables<\/name>\r\n <value>*<\/value>\r\n <\/property>\r\n <property>\r\n <name>entityType<\/name>\r\n <value>PROCESS<\/value>\r\n <\/property>\r\n <property>\r\n <name>sourceDatabases<\/name>\r\n <value>xademo,default<\/value>\r\n <\/property>\r\n <property>\r\n <name>feedInstancePaths<\/name>\r\n <value>NONE<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.bundle.application.path<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377<\/value>\r\n <\/property>\r\n <property>\r\n <name>logDir<\/name>\r\n
<value>hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/logs<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.use.system.libpath<\/name>\r\n <value>true<\/value>\r\n <\/property>\r\n <property>\r\n <name>userJMSNotificationEnabled<\/name>\r\n <value>true<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.wf.external.id<\/name>\r\n <value>0001250-160321130408525-oozie-oozi-W@user-action@0<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.wf.workflow.notification.url<\/name>\r\n <value>http:\/\/sandbox.hortonworks.com:11000\/oozie\/callback?id=0001250-160321130408525-oozie-oozi-W@user-action&status=$status<\/value>\r\n <\/property>\r\n <property>\r\n <name>datasource<\/name>\r\n <value>NA<\/value>\r\n <\/property>\r\n <property>\r\n <name>brokerUrl<\/name>\r\n <value>tcp:\/\/localhost:61616<\/value>\r\n <\/property>\r\n <proper
ty>\r\n <name>sourceCluster<\/name>\r\n <value>testCluster1<\/value>\r\n <\/property>\r\n <property>\r\n <name>distcpMaxMaps<\/name>\r\n <value>1<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.wf.subworkflow.classpath.inheritance<\/name>\r\n <value>true<\/value>\r\n <\/property>\r\n <property>\r\n <name>targetNN<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020<\/value>\r\n <\/property>\r\n <property>\r\n <name>brokerTTL<\/name>\r\n <value>4320<\/value>\r\n <\/property>\r\n <property>\r\n <name>userWorkflowName<\/name>\r\n <value>hive-mirroring-workflow<\/value>\r\n <\/property>\r\n <property>\r\n <name>clusterForJobRun<\/name>\r\n <value>testCluster1<\/value>\r\n <\/property>\r\n <property>\r\n <name>srcClusterName<\/name>\r\n <value>NA<\/value>\r\n <\/property>\r\n <property>\r\n <name>userBrokerUrl<\/name>\r\n <value>tcp:\/\/sandbox.hortonworks.com:61616?daemon=true<\/value>\r\n <\/property>\r
\n <property>\r\n <name>replicationMaxMaps<\/name>\r\n <value>5<\/value>\r\n <\/property>\r\n <property>\r\n <name>user.name<\/name>\r\n <value>root<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.libpath<\/name>\r\n <value>\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/lib<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.bundle.id<\/name>\r\n <value>0000734-160321130408525-oozie-oozi-B<\/value>\r\n <\/property>\r\n <property>\r\n <name>jobPriority<\/name>\r\n <value>NORMAL<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.action.yarn.tag<\/name>\r\n <value>0000735-160321130408525-oozie-oozi-C@2077@user-action<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.action.subworkflow.depth<\/name>\r\n <value>1<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.wf.application.path<\/name>\r\
n <value>hdfs:\/\/sandbox.hortonworks.com:8020\/tmp\/extensions\/hive-mirroring\/resources\/runtime\/hive-mirroring-workflow.xml<\/value>\r\n <\/property>\r\n <property>\r\n <name>targetMetastoreUri<\/name>\r\n <value>thrift:\/\/sandbox.hortonworks.com:9083<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.coord.application.path<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/coordinator.xml<\/value>\r\n <\/property>\r\n <property>\r\n <name>sourceMetastoreUri<\/name>\r\n <value>thrift:\/\/sandbox.hortonworks.com:9083<\/value>\r\n <\/property>\r\n <property>\r\n <name>shouldRecord<\/name>\r\n <value>false<\/value>\r\n <\/property>\r\n <property>\r\n <name>timeStamp<\/name>\r\n <value>2016-05-19-16-01<\/value>\r\n <\/property>\r\n <property>\r\n <name>clusterForJobRunWrite
EP<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020<\/value>\r\n <\/property>\r\n <property>\r\n <name>ENTITY_PATH<\/name>\r\n <value>\/apps\/falcon\/primaryCluster\/staging\/falcon\/workflows\/process\/hiveMirror11463038709928\/f8319c1e7fce6107b9facd0f5360b176_1463394572377\/DEFAULT\/coordinator.xml<\/value>\r\n <\/property>\r\n <property>\r\n <name>nominalTime<\/name>\r\n <value>2016-05-19-16-02<\/value>\r\n <\/property>\r\n <property>\r\n <name>systemJMSNotificationEnabled<\/name>\r\n <value>true<\/value>\r\n <\/property>\r\n <property>\r\n <name>userWorkflowEngine<\/name>\r\n <value>oozie<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.wf.parent.id<\/name>\r\n <value>0001250-160321130408525-oozie-oozi-W<\/value>\r\n <\/property>\r\n <property>\r\n <name>sourceNN<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020<\/value>\r\n <\/property>\r\n <property>\r\n <name>queueName<\/name>\r\n <value>default
<\/value>\r\n <\/property>\r\n <property>\r\n <name>falconDataOperation<\/name>\r\n <value>GENERATE<\/value>\r\n <\/property>\r\n <property>\r\n <name>workflowEngineUrl<\/name>\r\n <value>http:\/\/sandbox.hortonworks.com:11000\/oozie\/<\/value>\r\n <\/property>\r\n <property>\r\n <name>brokerImplClass<\/name>\r\n <value>org.apache.activemq.ActiveMQConnectionFactory<\/value>\r\n <\/property>\r\n <property>\r\n <name>userBrokerImplClass<\/name>\r\n <value>org.apache.activemq.ActiveMQConnectionFactory<\/value>\r\n <\/property>\r\n <property>\r\n <name>maxEvents<\/name>\r\n <value>-1<\/value>\r\n <\/property>\r\n <property>\r\n <name>ENTITY_NAME<\/name>\r\n <value>FALCON_PROCESS_DEFAULT_hiveMirror11463038709928<\/value>\r\n <\/property>\r\n <property>\r\n <name>availabilityFlag<\/name>\r\n <value>NA<\/value>\r\n <\/property>\r\n <property>\r\n <name>tdeEncryptionEnabled<\/name>\r\n <value>false<\/value>\r\n <\/property>\r\
n <property>\r\n <name>targetCluster<\/name>\r\n <value>testCluster1<\/value>\r\n <\/property>\r\n <property>\r\n <name>entityName<\/name>\r\n <value>hiveMirror11463038709928<\/value>\r\n <\/property>\r\n <property>\r\n <name>falconInputFeeds<\/name>\r\n <value>NONE<\/value>\r\n <\/property>\r\n <property>\r\n <name>userWorkflowVersion<\/name>\r\n <value>1.0<\/value>\r\n <\/property>\r\n <property>\r\n <name>cluster<\/name>\r\n <value>testCluster1<\/value>\r\n <\/property>\r\n <property>\r\n <name>colo.name<\/name>\r\n <value>testColo<\/value>\r\n <\/property>\r\n <property>\r\n <name>nameNode<\/name>\r\n <value>hdfs:\/\/sandbox.hortonworks.com:8020<\/value>\r\n <\/property>\r\n <property>\r\n <name>jobTracker<\/name>\r\n <value>sandbox.hortonworks.com:8050<\/value>\r\n <\/property>\r\n<\/configuration>","lastModTime":"Mon, 18 Jul 2016 17:18:27 GMT","run":0,"endTime":"Mon, 18 Jul 2016 17:18:27 GMT","externalId":"0001250
-160321130408525-oozie-oozi-W@user-action@0","appName":"falcon-dr-hive-workflow","id":"0001251-160321130408525-oozie-oozi-W","startTime":"Mon, 18 Jul 2016 17:18:19 GMT","parentId":"0001250-160321130408525-oozie-oozi-W","toString":"Workflow id[0001251-160321130408525-oozie-oozi-W] status[FAILED]","group":null,"consoleUrl":"http:\/\/sandbox.hortonworks.com:11000\/oozie?job=0001251-160321130408525-oozie-oozi-W","user":"root","actions":[{"errorMessage":null,"status":"OK","stats":null,"data":null,"transition":"last-event","externalStatus":"OK","cred":"null","conf":"","type":":START:","endTime":"Mon, 18 Jul 2016 17:18:21 GMT","externalId":"-","id":"0001251-160321130408525-oozie-oozi-W@:start:","startTime":"Mon, 18 Jul 2016 17:18:20 GMT","userRetryCount":0,"externalChildIDs":null,"name":":start:","errorCode":null,"trackerUri":"-","retries":0,"userRetryInterval":10,"toString":"Action name[:start:] status[OK]","consoleUrl":"-","userRetryMax":0},{"errorMessage":"variable [sourceHiveServer2Uri
] cannot be resolved","status":"FAILED","stats":null,"data":null,"transition":null,"externalStatus":null,"cred":"null","conf":"<java xmlns=\"uri:oozie:workflow:0.3\">\r\n <job-tracker>${jobTracker}<\/job-tracker>\r\n <name-node>${nameNode}<\/name-node>\r\n <configuration>\r\n <property>\r\n <!-- hadoop 2 parameter -->\r\n <name>oozie.launcher.mapreduce.job.user.classpath.first<\/name>\r\n <value>true<\/value>\r\n <\/property>\r\n <property>\r\n <name>mapred.job.queue.name<\/name>\r\n <value>${queueName}<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.launcher.mapred.job.priority<\/name>\r\n <value>${jobPriority}<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.use.system.libpath<\/name>\r\n <value>true<\/value>\r\n <\/property>\r\n <property>\r\n <name>oozie.action.sharelib.for.java<\/name>\r\n <value>distcp,hive,hive2,hcatalog<\/value>\r\n <\/property>\r\n <\/configuration>\r\n
<main-class>org.apache.falcon.hive.HiveDRTool<\/main-class>\r\n <arg>-Dmapred.job.queue.name=${queueName}<\/arg>\r\n <arg>-Dmapred.job.priority=${jobPriority}<\/arg>\r\n <arg>-falconLibPath<\/arg>\r\n <arg>${wf:conf(\"falcon.libpath\")}<\/arg>\r\n <arg>-sourceCluster<\/arg>\r\n <arg>${sourceCluster}<\/arg>\r\n <arg>-sourceMetastoreUri<\/arg>\r\n <arg>${sourceMetastoreUri}<\/arg>\r\n <arg>-sourceHiveServer2Uri<\/arg>\r\n <arg>${sourceHiveServer2Uri}<\/arg>\r\n <arg>-sourceDatabase<\/arg>\r\n <arg>${sourceDatabase}<\/arg>\r\n <arg>-sourceTable<\/arg>\r\n <arg>${sourceTable}<\/arg>\r\n <arg>-sourceStagingPath<\/arg>\r\n <arg>${sourceStagingPath}<\/arg>\r\n <arg>-sourceNN<\/arg>\r\n <arg>${sourceNN}<\/arg>\r\n <arg>-targetCluster<\/arg>\r\n <arg>${targetCluster}<\/arg>\r\n <arg>-targetMetastoreUri<\/arg>\r\n <arg>${targetMetastoreUri}<\/arg>\r\n <arg>-targetHiveServer2Uri<\/arg>\r\n <arg>${targetHiveServer2Uri}<\/arg>\r\n <arg>-targetStagingPath<\/arg>\r\n <a
rg>${targetStagingPath}<\/arg>\r\n <arg>-targetNN<\/arg>\r\n <arg>${targetNN}<\/arg>\r\n <arg>-maxEvents<\/arg>\r\n <arg>${maxEvents}<\/arg>\r\n <arg>-clusterForJobRun<\/arg>\r\n <arg>${clusterForJobRun}<\/arg>\r\n <arg>-clusterForJobRunWriteEP<\/arg>\r\n <arg>${clusterForJobRunWriteEP}<\/arg>\r\n <arg>-tdeEncryptionEnabled<\/arg>\r\n <arg>${tdeEncryptionEnabled}<\/arg>\r\n <arg>-jobName<\/arg>\r\n <arg>${jobName}-${nominalTime}<\/arg>\r\n <arg>-executionStage<\/arg>\r\n <arg>lastevents<\/arg>\r\n<\/java>","type":"java","endTime":null,"externalId":null,"id":"0001251-160321130408525-oozie-oozi-W@last-event","startTime":null,"userRetryCount":0,"externalChildIDs":null,"name":"last-event","errorCode":"EL_ERROR","trackerUri":null,"retries":0,"userRetryInterval":10,"toString":"Action name[last-event] status[FAILED]","consoleUrl":null,"userRetryMax":0}]}
+
+ var server = {
+ //"properties":[{key: "authentication", value: "kerberos"}]
+ "properties":[{key: "authentication", value: "simple"}]
+ };
+
+ exports.getJobs = getJobs;
+ exports.getJobById = getJobById;
+ exports.server = server;
+
+})();
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/package.json
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/package.json b/contrib/views/wfmanager/src/main/resources/ui/package.json
index d04d57c..ab9426a 100644
--- a/contrib/views/wfmanager/src/main/resources/ui/package.json
+++ b/contrib/views/wfmanager/src/main/resources/ui/package.json
@@ -29,28 +29,30 @@
"ember-cli-htmlbars": "^1.0.1",
"ember-cli-htmlbars-inline-precompile": "^0.3.1",
"ember-cli-inject-live-reload": "^1.3.1",
+ "ember-cli-less": "^1.5.3",
+ "ember-cli-moment-shim": "2.0.0",
"ember-cli-qunit": "^1.2.1",
"ember-cli-release": "0.2.8",
"ember-cli-sri": "^2.0.0",
"ember-cli-uglify": "^1.2.0",
+ "ember-cp-validations": "2.9.5",
"ember-data": "2.7.0",
"ember-disable-proxy-controllers": "^1.0.1",
"ember-export-application-global": "^1.0.4",
"ember-load-initializers": "^0.5.0",
+ "ember-moment": "6.1.0",
"ember-resolver": "^2.0.3",
"ember-spin-spinner": "0.2.4",
"ember-truth-helpers": "1.2.0",
- "loader.js": "^4.0.0",
- "ember-uploader": "1.0.0",
- "ember-validations": "~ 2.0.0-alpha.4"
+ "ember-uploader": "1.0.0",
+ "ember-uuid": "1.0.0",
+ "ember-validations": "~ 2.0.0-alpha.4",
+ "loader.js": "^4.0.0"
},
"ember-addon": {
"paths": [
- "lib/favicon"
+ "externaladdons/hdfs-directory-viewer"
],
- "name": "files",
- "paths": [
- "externaladdons/hdfs-directory-viewer"
- ]
+ "name": "files"
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/assets/favicon.ico
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/assets/favicon.ico b/contrib/views/wfmanager/src/main/resources/ui/public/assets/favicon.ico
new file mode 100644
index 0000000..5d95710
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/assets/favicon.ico differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/assets/join.png
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/assets/join.png b/contrib/views/wfmanager/src/main/resources/ui/public/assets/join.png
new file mode 100644
index 0000000..3fafaaf
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/assets/join.png differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/assets/logo.png
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/assets/logo.png b/contrib/views/wfmanager/src/main/resources/ui/public/assets/logo.png
new file mode 100644
index 0000000..e3b27c4
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/assets/logo.png differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/assets/play.png
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/assets/play.png b/contrib/views/wfmanager/src/main/resources/ui/public/assets/play.png
new file mode 100644
index 0000000..d6fa7ba
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/assets/play.png differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/assets/sitemap.png
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/assets/sitemap.png b/contrib/views/wfmanager/src/main/resources/ui/public/assets/sitemap.png
new file mode 100644
index 0000000..d0316a4
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/assets/sitemap.png differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/assets/stop.png
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/assets/stop.png b/contrib/views/wfmanager/src/main/resources/ui/public/assets/stop.png
new file mode 100644
index 0000000..a9e6336
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/assets/stop.png differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/loader.gif
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/loader.gif b/contrib/views/wfmanager/src/main/resources/ui/public/loader.gif
new file mode 100644
index 0000000..71a4cc7
Binary files /dev/null and b/contrib/views/wfmanager/src/main/resources/ui/public/loader.gif differ
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/bundle.xml
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/bundle.xml b/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/bundle.xml
new file mode 100644
index 0000000..c435682
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/bundle.xml
@@ -0,0 +1,32 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<bundle-app name='bundle-app' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns='uri:oozie:bundle:0.1'>
+ <coordinator name='coord-1'>
+ <app-path>${nameNode}/user/${userName}/${examplesRoot}/apps/aggregator/coordinator.xml</app-path>
+ <configuration>
+ <property>
+ <name>start</name>
+ <value>${start}</value>
+ </property>
+ <property>
+ <name>end</name>
+ <value>${end}</value>
+ </property>
+ </configuration>
+ </coordinator>
+</bundle-app>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/coordinator.xml
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/coordinator.xml b/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/coordinator.xml
new file mode 100644
index 0000000..7bb2629
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/public/sampledata/coordinator.xml
@@ -0,0 +1,113 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<coordinator-app name="coord-input-logic" frequency="${coord:hours(1)}" start="${start}" end="${end}" timezone="UTC"
+ xmlns="uri:oozie:coordinator:0.5">
+ <controls>
+ <concurrency>1</concurrency>
+ </controls>
+ <parameters>
+ <configuration>
+ <property>
+ <name>ds</name>
+ <value>ewr</value>
+ </property>
+ </configuration>
+ </parameters>
+ <datasets>
+ <dataset name="data-1" frequency="${coord:minutes(20)}" initial-instance="2010-01-01T00:00Z" timezone="UTC">
+ <uri-template>${nameNode}/user/${coord:user()}/${examplesRoot}/input-data/rawLogs/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}</uri-template>
+ </dataset>
+ <dataset name="data-2" frequency="${coord:minutes(20)}" initial-instance="2010-01-01T00:00Z" timezone="UTC">
+ <uri-template>${nameNode}/user/${coord:user()}/${examplesRoot}/input-data/rawLogs-2/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}</uri-template>
+ </dataset>
+ <dataset name="data-3" frequency="${coord:minutes(20)}" initial-instance="2010-01-01T00:00Z" timezone="UTC">
+ <uri-template>${nameNode}/user/${coord:user()}/${examplesRoot}/input-data/rawLogs-3/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}</uri-template>
+ </dataset>
+ <dataset name="data-4" frequency="${coord:minutes(20)}" initial-instance="2010-01-01T00:00Z" timezone="UTC">
+ <uri-template>${nameNode}/user/${coord:user()}/${examplesRoot}/input-data/rawLogs-4/${YEAR}/${MONTH}/${DAY}/${HOUR}/${MINUTE}</uri-template>
+ </dataset>
+ <dataset name="output" frequency="${coord:hours(1)}" initial-instance="2010-01-01T01:00Z" timezone="UTC">
+ <uri-template>${nameNode}/user/${coord:user()}/${examplesRoot}/output-data/inputLogic/${YEAR}/${MONTH}/${DAY}/${HOUR}</uri-template>
+ </dataset>
+ <dataset name="output-1" frequency="${coord:hours(1)}" initial-instance="2010-01-01T01:00Z" timezone="UTC">
+ <uri-template>${nameNode}/user/${coord:user()}/${examplesRoot}/output-data/inputLogic/${YEAR}/${MONTH}/${DAY}/${HOUR}</uri-template>
+ </dataset>
+ </datasets>
+ <input-events>
+ <data-in name="input-1" dataset="data-1">
+ <start-instance>${coord:current(-2)}</start-instance>
+ <end-instance>${coord:current(0)}</end-instance>
+ </data-in>
+ <data-in name="input-2" dataset="data-2">
+ <start-instance>${coord:current(-2)}</start-instance>
+ <end-instance>${coord:current(0)}</end-instance>
+ </data-in>
+ <data-in name="input-3" dataset="data-4">
+ <instance>2016-08-01T00:00Z</instance>
+ <instance>2016-08-02T00:00Z</instance>
+ <instance>2016-08-03T00:00Z</instance>
+ </data-in>
+ </input-events>
+ <!--input-events>
+ <or name="c1">
+ <data-in name="d1" dataset="data-1"></data-in>
+ <data-in name="d4" dataset="data-4"></data-in>
+ <and name="nc1">
+ <data-in name="d2" dataset="data-2"></data-in>
+ <data-in name="d3" dataset="data-3"></data-in>
+ </and>
+ </or>
+ </input-events-->
+ <input-logic>
+ <or name="input">
+ <data-in dataset="input-1"/>
+ <data-in dataset="input-2"/>
+ </or>
+ </input-logic>
+ <output-events>
+ <data-out name="output" dataset="output">
+ <instance>${coord:current(0)}</instance>
+ </data-out>
+ <data-out name="output-1" dataset="output-1">
+ <instance>${coord:current(0)}</instance>
+ </data-out>
+ </output-events>
+ <action>
+ <workflow>
+ <app-path>${nameNode}/user/${coord:user()}/${examplesRoot}/apps/coord-input-logic</app-path>
+ <configuration>
+ <property>
+ <name>nameNode</name>
+ <value>${nameNode}</value>
+ </property>
+ <property>
+ <name>queueName</name>
+ <value>${queueName}</value>
+ </property>
+ <property>
+ <name>outputData</name>
+ <value>${coord:dataOut('output')}</value>
+ </property>
+ <property>
+ <name>inputData</name>
+ <value>${coord:dataIn('input')}</value>
+ </property>
+ </configuration>
+ </workflow>
+ </action>
+</coordinator-app>
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/.gitkeep
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/.gitkeep b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/.gitkeep
new file mode 100644
index 0000000..e69de29
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-config-test.js
new file mode 100644
index 0000000..a3fe9f2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-config-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bundle-config', 'Integration | Component | bundle config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{bundle-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#bundle-config}}
+ template block text
+ {{/bundle-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-coord-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-coord-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-coord-config-test.js
new file mode 100644
index 0000000..910d0e8
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/bundle-coord-config-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('bundle-coord-config', 'Integration | Component | bundle coord config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{bundle-coord-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#bundle-coord-config}}
+ template block text
+ {{/bundle-coord-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/conditional-data-input-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/conditional-data-input-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/conditional-data-input-test.js
new file mode 100644
index 0000000..baacde2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/conditional-data-input-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('conditional-data-input', 'Integration | Component | conditional data input', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{conditional-data-input}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#conditional-data-input}}
+ template block text
+ {{/conditional-data-input}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/confirmation-dialog-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/confirmation-dialog-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/confirmation-dialog-test.js
new file mode 100644
index 0000000..8a366aa
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/confirmation-dialog-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('confirmation-dialog', 'Integration | Component | confirmation dialog', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{confirmation-dialog}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#confirmation-dialog}}
+ template block text
+ {{/confirmation-dialog}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/coord-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/coord-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/coord-config-test.js
new file mode 100644
index 0000000..3eaee2b
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/coord-config-test.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('coord-config', 'Integration | Component | coord config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{coord-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#coord-config}}
+ template block text
+ {{/coord-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-output-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-output-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-output-config-test.js
new file mode 100644
index 0000000..86a11f2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-output-config-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('data-input-output-config', 'Integration | Component | data input output config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{data-input-output-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#data-input-output-config}}
+ template block text
+ {{/data-input-output-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-test.js
new file mode 100644
index 0000000..64c63eb
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/data-input-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('data-input', 'Integration | Component | data input', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{data-input}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#data-input}}
+ template block text
+ {{/data-input}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/dataset-config-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/dataset-config-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/dataset-config-test.js
new file mode 100644
index 0000000..622fae5
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/dataset-config-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('dataset-config', 'Integration | Component | dataset config', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{dataset-config}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#dataset-config}}
+ template block text
+ {{/dataset-config}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/date-with-expr-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/date-with-expr-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/date-with-expr-test.js
new file mode 100644
index 0000000..31da9c2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/date-with-expr-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('date-with-expr', 'Integration | Component | date with expr', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{date-with-expr}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#date-with-expr}}
+ template block text
+ {{/date-with-expr}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/designer-workspace-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/designer-workspace-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/designer-workspace-test.js
new file mode 100644
index 0000000..a133fa1
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/designer-workspace-test.js
@@ -0,0 +1,40 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('designer-workspace', 'Integration | Component | designer workspace', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{designer-workspace}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#designer-workspace}}
+ template block text
+ {{/designer-workspace}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/distcp-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/distcp-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/distcp-action-info-test.js
new file mode 100644
index 0000000..5165c24
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/distcp-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('distcp-action-info', 'Integration | Component | distcp action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{distcp-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#distcp-action-info}}
+ template block text
+ {{/distcp-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/7c7412ed/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/email-action-info-test.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/email-action-info-test.js b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/email-action-info-test.js
new file mode 100644
index 0000000..9b76e58
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/tests/integration/components/email-action-info-test.js
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+import { moduleForComponent, test } from 'ember-qunit';
+import hbs from 'htmlbars-inline-precompile';
+
+moduleForComponent('email-action-info', 'Integration | Component | email action info', {
+ integration: true
+});
+
+test('it renders', function(assert) {
+ // Set any properties with this.set('myProperty', 'value');
+ // Handle any actions with this.on('myAction', function(val) { ... });"
+
+ this.render(hbs`{{email-action-info}}`);
+
+ assert.equal(this.$().text().trim(), '');
+
+ // Template block usage:"
+ this.render(hbs`
+ {{#email-action-info}}
+ template block text
+ {{/email-action-info}}
+ `);
+
+ assert.equal(this.$().text().trim(), 'template block text');
+});