aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJing Lu <lvjing5@huawei.com>2017-07-27 05:04:36 +0000
committerGerrit Code Review <gerrit@opnfv.org>2017-07-27 05:04:37 +0000
commitd184d8714e543e4f2497db682154820f7eecf1de (patch)
tree0dd1709c01ff9f34b4d39dad4af50ff6b789234f
parentd9b9b8970312e13f798a367439cfc2c333c7fca4 (diff)
parentedbe3568a052da8afd24b6877c4c6fdcc7627ba3 (diff)
Merge "Yardstick GUI & GUI deployment"
-rw-r--r--api/database/v2/models.py2
-rw-r--r--api/resources/v2/images.py2
-rw-r--r--api/resources/v2/tasks.py3
-rw-r--r--api/resources/v2/testcases.py2
-rw-r--r--api/urls.py3
-rw-r--r--docker/Dockerfile1
-rwxr-xr-xdocker/nginx.sh31
-rwxr-xr-xdocker/supervisor.sh26
-rwxr-xr-xdocker/uwsgi.sh (renamed from api/api-prepare.sh)54
-rw-r--r--gui/Gruntfile.js492
-rw-r--r--gui/app/404.html152
-rw-r--r--gui/app/favicon.icobin0 -> 4286 bytes
-rw-r--r--gui/app/images/back.pngbin0 -> 1976 bytes
-rw-r--r--gui/app/images/checkno.pngbin0 -> 5849 bytes
-rw-r--r--gui/app/images/checkyes.pngbin0 -> 6423 bytes
-rw-r--r--gui/app/images/close.pngbin0 -> 1211 bytes
-rw-r--r--gui/app/images/loading.gifbin0 -> 130310 bytes
-rw-r--r--gui/app/images/loading2.gifbin0 -> 25405 bytes
-rw-r--r--gui/app/images/statusno.pngbin0 -> 3861 bytes
-rw-r--r--gui/app/images/statusyes.pngbin0 -> 2577 bytes
-rw-r--r--gui/app/images/url.json1
-rw-r--r--gui/app/images/yeoman.pngbin0 -> 13501 bytes
-rw-r--r--gui/app/index.html111
-rw-r--r--gui/app/robots.txt4
-rw-r--r--gui/app/scripts/app.js30
-rw-r--r--gui/app/scripts/controllers/container.controller.js182
-rw-r--r--gui/app/scripts/controllers/content.controller.js136
-rw-r--r--gui/app/scripts/controllers/detail.controller.js384
-rw-r--r--gui/app/scripts/controllers/image.controller.js166
-rw-r--r--gui/app/scripts/controllers/main.js725
-rw-r--r--gui/app/scripts/controllers/pod.controller.js179
-rw-r--r--gui/app/scripts/controllers/project.controller.js160
-rw-r--r--gui/app/scripts/controllers/projectDetail.controller.js690
-rw-r--r--gui/app/scripts/controllers/report.controller.js115
-rw-r--r--gui/app/scripts/controllers/suitecreate.controller.js104
-rw-r--r--gui/app/scripts/controllers/suitedetail.controller.js48
-rw-r--r--gui/app/scripts/controllers/task.controller.js175
-rw-r--r--gui/app/scripts/controllers/taskModify.controller.js533
-rw-r--r--gui/app/scripts/controllers/testcase.controller.js154
-rw-r--r--gui/app/scripts/controllers/testcasedetail.controller.js50
-rw-r--r--gui/app/scripts/controllers/testsuit.controller.js119
-rw-r--r--gui/app/scripts/factory/main.factory.js247
-rw-r--r--gui/app/scripts/router.config.js184
-rw-r--r--gui/app/styles/main.css208
-rw-r--r--gui/app/views/container.html134
-rw-r--r--gui/app/views/content.html0
-rw-r--r--gui/app/views/environmentDetail.html143
-rw-r--r--gui/app/views/environmentList.html155
-rw-r--r--gui/app/views/layout/footer.html5
-rw-r--r--gui/app/views/layout/header.html43
-rw-r--r--gui/app/views/layout/sideNav.html141
-rw-r--r--gui/app/views/layout/sideNav2.html108
-rw-r--r--gui/app/views/main.html174
-rw-r--r--gui/app/views/main2.html174
-rw-r--r--gui/app/views/modal/chooseContainer.html15
-rw-r--r--gui/app/views/modal/deleteConfirm.html19
-rw-r--r--gui/app/views/modal/environmentDialog.html330
-rw-r--r--gui/app/views/modal/projectCreate.html21
-rw-r--r--gui/app/views/modal/suiteName.html18
-rw-r--r--gui/app/views/modal/taskCreate.html134
-rw-r--r--gui/app/views/podupload.html136
-rw-r--r--gui/app/views/projectList.html57
-rw-r--r--gui/app/views/projectdetail.html97
-rw-r--r--gui/app/views/report.html56
-rw-r--r--gui/app/views/suite.html149
-rw-r--r--gui/app/views/suitedetail.html110
-rw-r--r--gui/app/views/taskList.html62
-rw-r--r--gui/app/views/taskmodify.html162
-rw-r--r--gui/app/views/testcasechoose.html48
-rw-r--r--gui/app/views/testcasedetail.html110
-rw-r--r--gui/app/views/testcaselist.html150
-rw-r--r--gui/app/views/uploadImage.html145
-rw-r--r--gui/bower.json45
-rwxr-xr-xgui/gui.sh8
-rw-r--r--gui/package.json43
-rw-r--r--gui/test/.jshintrc18
-rw-r--r--gui/test/karma.conf.js93
-rw-r--r--gui/test/spec/controllers/main.js23
-rwxr-xr-xinstall.sh5
79 files changed, 8554 insertions, 50 deletions
diff --git a/api/database/v2/models.py b/api/database/v2/models.py
index 64d49cc9d..1e85559cb 100644
--- a/api/database/v2/models.py
+++ b/api/database/v2/models.py
@@ -31,7 +31,7 @@ class V2Environment(Base):
class V2Openrc(Base):
- __tablename__ = 'V2_openrc'
+ __tablename__ = 'v2_openrc'
id = Column(Integer, primary_key=True)
uuid = Column(String(30))
name = Column(String(30))
diff --git a/api/resources/v2/images.py b/api/resources/v2/images.py
index 8755e5265..8359e105b 100644
--- a/api/resources/v2/images.py
+++ b/api/resources/v2/images.py
@@ -37,6 +37,8 @@ class V2Images(ApiResource):
else:
images = [self.get_info(change_obj_to_dict(i)) for i in images_list]
status = 1 if all(i['status'] == 'ACTIVE' for i in images) else 0
+ if not images:
+ status = 0
return result_handler(consts.API_SUCCESS, {'status': status, 'images': images})
diff --git a/api/resources/v2/tasks.py b/api/resources/v2/tasks.py
index b64f5ef24..885a190c6 100644
--- a/api/resources/v2/tasks.py
+++ b/api/resources/v2/tasks.py
@@ -114,7 +114,8 @@ class V2Task(ApiResource):
if project.tasks:
LOG.info('update tasks in project')
- new_task_list = project.tasks.split(',').remove(task_id)
+ new_task_list = project.tasks.split(',')
+ new_task_list.remove(task_id)
if new_task_list:
new_tasks = ','.join(new_task_list)
else:
diff --git a/api/resources/v2/testcases.py b/api/resources/v2/testcases.py
index ca88e9856..b47a8f6b7 100644
--- a/api/resources/v2/testcases.py
+++ b/api/resources/v2/testcases.py
@@ -25,7 +25,7 @@ class V2Testcases(ApiResource):
def get(self):
param = Param({})
testcase_list = Testcase().list_all(param)
- return result_handler(consts.API_SUCCESS, testcase_list)
+ return result_handler(consts.API_SUCCESS, {'testcases': testcase_list})
def post(self):
return self._dispatch_post()
diff --git a/api/urls.py b/api/urls.py
index 2211348f3..3fef91af8 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -26,15 +26,18 @@ urlpatterns = [
Url('/api/v2/yardstick/environments/action', 'v2_environments'),
Url('/api/v2/yardstick/environments/<environment_id>', 'v2_environment'),
+ Url('/api/v2/yardstick/openrcs', 'v2_openrcs'),
Url('/api/v2/yardstick/openrcs/action', 'v2_openrcs'),
Url('/api/v2/yardstick/openrcs/<openrc_id>', 'v2_openrc'),
+ Url('/api/v2/yardstick/pods', 'v2_pods'),
Url('/api/v2/yardstick/pods/action', 'v2_pods'),
Url('/api/v2/yardstick/pods/<pod_id>', 'v2_pod'),
Url('/api/v2/yardstick/images', 'v2_images'),
Url('/api/v2/yardstick/images/action', 'v2_images'),
+ Url('/api/v2/yardstick/containers', 'v2_containers'),
Url('/api/v2/yardstick/containers/action', 'v2_containers'),
Url('/api/v2/yardstick/containers/<container_id>', 'v2_container'),
diff --git a/docker/Dockerfile b/docker/Dockerfile
index 2c4270a09..b48a550bf 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -37,6 +37,7 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/storperf ${ST
WORKDIR ${YARDSTICK_REPO_DIR}
RUN ${YARDSTICK_REPO_DIR}/install.sh
+RUN ${YARDSTICK_REPO_DIR}/docker/supervisor.sh
RUN echo "daemon off;" >> /etc/nginx/nginx.conf
diff --git a/docker/nginx.sh b/docker/nginx.sh
new file mode 100755
index 000000000..26937d134
--- /dev/null
+++ b/docker/nginx.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# nginx config
+nginx_config='/etc/nginx/conf.d/yardstick.conf'
+
+if [[ ! -e "${nginx_config}" ]];then
+
+ cat << EOF > "${nginx_config}"
+server {
+ listen 5000;
+ server_name localhost;
+ index index.htm index.html;
+ location / {
+ include uwsgi_params;
+ uwsgi_pass unix:///var/run/yardstick.sock;
+ }
+
+ location /gui/ {
+ alias /etc/nginx/yardstick/gui/;
+ }
+}
+EOF
+fi
diff --git a/docker/supervisor.sh b/docker/supervisor.sh
new file mode 100755
index 000000000..b67de2212
--- /dev/null
+++ b/docker/supervisor.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# nginx service start when boot
+supervisor_config='/etc/supervisor/conf.d/yardstick.conf'
+
+if [[ ! -e "${supervisor_config}" ]];then
+ cat << EOF > "${supervisor_config}"
+[supervisord]
+nodaemon = true
+
+[program:nginx]
+command = service nginx restart
+
+[program:yardstick_uwsgi]
+directory = /etc/yardstick
+command = uwsgi -i yardstick.ini
+EOF
+fi
diff --git a/api/api-prepare.sh b/docker/uwsgi.sh
index 7632d9da9..cf4612332 100755
--- a/api/api-prepare.sh
+++ b/docker/uwsgi.sh
@@ -1,6 +1,6 @@
#!/bin/bash
##############################################################################
-# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
@@ -12,6 +12,13 @@
# generate uwsgi config file
mkdir -p /etc/yardstick
+
+# create api log directory
+mkdir -p /var/log/yardstick
+
+# create yardstick.sock for communicating
+touch /var/run/yardstick.sock
+
uwsgi_config='/etc/yardstick/yardstick.ini'
if [[ ! -e "${uwsgi_config}" ]];then
@@ -37,48 +44,3 @@ EOF
echo "virtualenv = ${YARDSTICK_VENV}" >> "${uwsgi_config}"
fi
fi
-
-# nginx config
-nginx_config='/etc/nginx/conf.d/yardstick.conf'
-
-if [[ ! -e "${nginx_config}" ]];then
-
- cat << EOF > "${nginx_config}"
-server {
- listen 5000;
- server_name localhost;
- index index.htm index.html;
- location / {
- include uwsgi_params;
- uwsgi_pass unix:///var/run/yardstick.sock;
- }
-}
-EOF
-fi
-
-# nginx service start when boot
-supervisor_config='/etc/supervisor/conf.d/yardstick.conf'
-
-if [[ ! -e "${supervisor_config}" ]];then
- cat << EOF > "${supervisor_config}"
-[supervisord]
-nodaemon = true
-
-[program:yardstick_nginx]
-user = root
-command = service nginx restart
-autorestart = true
-
-[program:yardstick_uwsgi]
-user = root
-directory = /etc/yardstick
-command = uwsgi -i yardstick.ini
-autorestart = true
-EOF
-fi
-
-# create api log directory
-mkdir -p /var/log/yardstick
-
-# create yardstick.sock for communicating
-touch /var/run/yardstick.sock
diff --git a/gui/Gruntfile.js b/gui/Gruntfile.js
new file mode 100644
index 000000000..171d65add
--- /dev/null
+++ b/gui/Gruntfile.js
@@ -0,0 +1,492 @@
+// Generated on 2017-05-31 using generator-angular 0.15.1
+'use strict';
+
+// # Globbing
+// for performance reasons we're only matching one level down:
+// 'test/spec/{,*/}*.js'
+// use this if you want to recursively match all subfolders:
+// 'test/spec/**/*.js'
+
+module.exports = function(grunt) {
+
+ // Time how long tasks take. Can help when optimizing build times
+ require('time-grunt')(grunt);
+
+ // Automatically load required Grunt tasks
+ require('jit-grunt')(grunt, {
+ useminPrepare: 'grunt-usemin',
+ ngtemplates: 'grunt-angular-templates',
+ cdnify: 'grunt-google-cdn'
+ });
+
+ // Configurable paths for the application
+ var appConfig = {
+ app: require('./bower.json').appPath || 'app',
+ dist: 'dist'
+ };
+
+ // Define the configuration for all the tasks
+ grunt.initConfig({
+
+ // Project settings
+ yeoman: appConfig,
+
+ // Watches files for changes and runs tasks based on the changed files
+ watch: {
+ bower: {
+ files: ['bower.json'],
+ tasks: ['wiredep']
+ },
+ js: {
+ files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
+ tasks: ['newer:jshint:all', 'newer:jscs:all'],
+ options: {
+ livereload: '<%= connect.options.livereload %>'
+ }
+ },
+ jsTest: {
+ files: ['test/spec/{,*/}*.js'],
+ tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
+ },
+ styles: {
+ files: ['<%= yeoman.app %>/styles/{,*/}*.css'],
+ tasks: ['newer:copy:styles', 'postcss']
+ },
+ gruntfile: {
+ files: ['Gruntfile.js']
+ },
+ livereload: {
+ options: {
+ livereload: '<%= connect.options.livereload %>'
+ },
+ files: [
+ '<%= yeoman.app %>/{,*/}*.html',
+ '.tmp/styles/{,*/}*.css',
+ '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
+ ]
+ }
+ },
+
+ // The actual grunt server settings
+ connect: {
+ options: {
+ port: 9099,
+ // Change this to '0.0.0.0' to access the server from outside.
+ hostname: 'localhost',
+ livereload: 35745
+ },
+ livereload: {
+ options: {
+ open: true,
+ middleware: function(connect) {
+ return [
+ connect.static('.tmp'),
+ connect().use(
+ '/bower_components',
+ connect.static('./bower_components')
+ ),
+ connect().use(
+ '/app/styles',
+ connect.static('./app/styles')
+ ),
+ connect.static(appConfig.app)
+ ];
+ }
+ }
+ },
+ test: {
+ options: {
+ port: 9001,
+ middleware: function(connect) {
+ return [
+ connect.static('.tmp'),
+ connect.static('test'),
+ connect().use(
+ '/bower_components',
+ connect.static('./bower_components')
+ ),
+ connect.static(appConfig.app)
+ ];
+ }
+ }
+ },
+ dist: {
+ options: {
+ open: true,
+ base: '<%= yeoman.dist %>'
+ }
+ }
+ },
+
+ // Make sure there are no obvious mistakes
+ jshint: {
+ options: {
+ jshintrc: '.jshintrc',
+ reporter: require('jshint-stylish')
+ },
+ all: {
+ src: [
+ 'Gruntfile.js',
+ '<%= yeoman.app %>/scripts/{,*/}*.js'
+ ]
+ },
+ test: {
+ options: {
+ jshintrc: 'test/.jshintrc'
+ },
+ src: ['test/spec/{,*/}*.js']
+ }
+ },
+
+ // Make sure code styles are up to par
+ jscs: {
+ options: {
+ config: '.jscsrc',
+ verbose: true
+ },
+ all: {
+ src: [
+ 'Gruntfile.js',
+ '<%= yeoman.app %>/scripts/{,*/}*.js'
+ ]
+ },
+ test: {
+ src: ['test/spec/{,*/}*.js']
+ }
+ },
+
+ // Empties folders to start fresh
+ clean: {
+ dist: {
+ files: [{
+ dot: true,
+ src: [
+ '.tmp',
+ '<%= yeoman.dist %>/{,*/}*',
+ '!<%= yeoman.dist %>/.git{,*/}*'
+ ]
+ }]
+ },
+ server: '.tmp'
+ },
+
+ // Add vendor prefixed styles
+ postcss: {
+ options: {
+ processors: [
+ require('autoprefixer-core')({ browsers: ['last 1 version'] })
+ ]
+ },
+ server: {
+ options: {
+ map: true
+ },
+ files: [{
+ expand: true,
+ cwd: '.tmp/styles/',
+ src: '{,*/}*.css',
+ dest: '.tmp/styles/'
+ }]
+ },
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '.tmp/styles/',
+ src: '{,*/}*.css',
+ dest: '.tmp/styles/'
+ }]
+ }
+ },
+
+ // Automatically inject Bower components into the app
+ wiredep: {
+ app: {
+ src: ['<%= yeoman.app %>/index.html'],
+ ignorePath: /\.\.\//
+ },
+ test: {
+ devDependencies: true,
+ src: '<%= karma.unit.configFile %>',
+ ignorePath: /\.\.\//,
+ fileTypes: {
+ js: {
+ block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
+ detect: {
+ js: /'(.*\.js)'/gi
+ },
+ replace: {
+ js: '\'{{filePath}}\','
+ }
+ }
+ }
+ }
+ },
+
+ // Renames files for browser caching purposes
+ filerev: {
+ dist: {
+ src: [
+ '<%= yeoman.dist %>/scripts/{,*/}*.js',
+ '<%= yeoman.dist %>/styles/{,*/}*.css',
+ '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
+ '<%= yeoman.dist %>/styles/fonts/*'
+ ]
+ }
+ },
+
+ // Reads HTML for usemin blocks to enable smart builds that automatically
+ // concat, minify and revision files. Creates configurations in memory so
+ // additional tasks can operate on them
+ useminPrepare: {
+ html: '<%= yeoman.app %>/index.html',
+ options: {
+ dest: '<%= yeoman.dist %>',
+ flow: {
+ html: {
+ steps: {
+ js: ['concat', 'uglifyjs'],
+ css: ['cssmin']
+ },
+ post: {}
+ }
+ }
+ }
+ },
+
+ // Performs rewrites based on filerev and the useminPrepare configuration
+ usemin: {
+ html: ['<%= yeoman.dist %>/{,*/}*.html'],
+ css: ['<%= yeoman.dist %>/styles/{,*/}*.css'],
+ js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
+ options: {
+ assetsDirs: [
+ '<%= yeoman.dist %>',
+ '<%= yeoman.dist %>/images',
+ '<%= yeoman.dist %>/styles'
+ ],
+ patterns: {
+ js: [
+ [/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp|svg))/g, 'Replacing references to images']
+ ]
+ }
+ }
+ },
+
+ // The following *-min tasks will produce minified files in the dist folder
+ // By default, your `index.html`'s <!-- Usemin block --> will take care of
+ // minification. These next options are pre-configured if you do not wish
+ // to use the Usemin blocks.
+ // cssmin: {
+ // dist: {
+ // files: {
+ // '<%= yeoman.dist %>/styles/main.css': [
+ // '.tmp/styles/{,*/}*.css'
+ // ]
+ // }
+ // }
+ // },
+ // uglify: {
+ // dist: {
+ // files: {
+ // '<%= yeoman.dist %>/scripts/scripts.js': [
+ // '<%= yeoman.dist %>/scripts/scripts.js'
+ // ]
+ // }
+ // }
+ // },
+ // concat: {
+ // dist: {}
+ // },
+
+ imagemin: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/images',
+ src: '{,*/}*.{png,jpg,jpeg,gif}',
+ dest: '<%= yeoman.dist %>/images'
+ }]
+ }
+ },
+
+ svgmin: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.app %>/images',
+ src: '{,*/}*.svg',
+ dest: '<%= yeoman.dist %>/images'
+ }]
+ }
+ },
+
+ htmlmin: {
+ dist: {
+ options: {
+ collapseWhitespace: true,
+ conservativeCollapse: true,
+ collapseBooleanAttributes: true,
+ removeCommentsFromCDATA: true
+ },
+ files: [{
+ expand: true,
+ cwd: '<%= yeoman.dist %>',
+ src: ['*.html'],
+ dest: '<%= yeoman.dist %>'
+ }]
+ }
+ },
+
+ ngtemplates: {
+ dist: {
+ options: {
+ module: 'yardStickGui2App',
+ htmlmin: '<%= htmlmin.dist.options %>',
+ usemin: 'scripts/scripts.js'
+ },
+ cwd: '<%= yeoman.app %>',
+ src: 'views/{,*/}*.html',
+ dest: '.tmp/templateCache.js'
+ }
+ },
+
+ // ng-annotate tries to make the code safe for minification automatically
+ // by using the Angular long form for dependency injection.
+ ngAnnotate: {
+ dist: {
+ files: [{
+ expand: true,
+ cwd: '.tmp/concat/scripts',
+ src: '*.js',
+ dest: '.tmp/concat/scripts'
+ }]
+ }
+ },
+
+ // Replace Google CDN references
+ cdnify: {
+ dist: {
+ html: ['<%= yeoman.dist %>/*.html']
+ }
+ },
+
+ // Copies remaining files to places other tasks can use
+ copy: {
+ dist: {
+ files: [{
+ expand: true,
+ dot: true,
+ cwd: '<%= yeoman.app %>',
+ dest: '<%= yeoman.dist %>',
+ src: [
+ '*.{ico,png,txt}',
+ '*.html',
+ 'images/{,*/}*.{webp}',
+ 'styles/fonts/{,*/}*.*'
+ ]
+ }, {
+ expand: true,
+ cwd: '.tmp/images',
+ dest: '<%= yeoman.dist %>/images',
+ src: ['generated/*']
+ }, {
+ expand: true,
+ cwd: 'bower_components/bootstrap/dist',
+ src: 'fonts/*',
+ dest: '<%= yeoman.dist %>'
+ },
+ {
+ expand: true,
+ cwd: 'bower_components/components-font-awesome',
+ src: 'fonts/*',
+ dest: '<%=yeoman.dist%>'
+ }
+ ]
+ },
+ styles: {
+ expand: true,
+ cwd: '<%= yeoman.app %>/styles',
+ dest: '.tmp/styles/',
+ src: '{,*/}*.css'
+ }
+ },
+
+ // Run some tasks in parallel to speed up the build process
+ concurrent: {
+ server: [
+ 'copy:styles'
+ ],
+ test: [
+ 'copy:styles'
+ ],
+ dist: [
+ 'copy:styles',
+ 'imagemin',
+ 'svgmin'
+ ]
+ },
+
+ // Test settings
+ karma: {
+ unit: {
+ configFile: 'test/karma.conf.js',
+ singleRun: true
+ }
+ }
+ });
+
+
+ grunt.registerTask('serve', 'Compile then start a connect web server', function(target) {
+ if (target === 'dist') {
+ return grunt.task.run(['build', 'connect:dist:keepalive']);
+ }
+
+ grunt.task.run([
+ 'clean:server',
+ 'wiredep',
+ 'concurrent:server',
+ 'postcss:server',
+ 'connect:livereload',
+ 'watch'
+ ]);
+ });
+
+ grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function(target) {
+ grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
+ grunt.task.run(['serve:' + target]);
+ });
+
+ grunt.registerTask('test', [
+ 'clean:server',
+ 'wiredep',
+ 'concurrent:test',
+ 'postcss',
+ 'connect:test',
+ 'karma'
+ ]);
+
+ grunt.registerTask('build', [
+ 'clean:dist',
+ 'wiredep',
+ 'useminPrepare',
+ 'concurrent:dist',
+ 'postcss',
+ 'ngtemplates',
+ 'concat',
+ 'ngAnnotate',
+ 'copy:dist',
+ // 'cdnify',
+ 'cssmin',
+ 'uglify',
+ 'filerev',
+ 'usemin',
+ 'htmlmin'
+ ]);
+
+ grunt.registerTask('default', [
+ 'newer:jshint',
+ 'newer:jscs',
+ 'test',
+ 'build'
+ ]);
+};
diff --git a/gui/app/404.html b/gui/app/404.html
new file mode 100644
index 000000000..899828a3c
--- /dev/null
+++ b/gui/app/404.html
@@ -0,0 +1,152 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>Page Not Found :(</title>
+ <style>
+ ::-moz-selection {
+ background: #b3d4fc;
+ text-shadow: none;
+ }
+
+ ::selection {
+ background: #b3d4fc;
+ text-shadow: none;
+ }
+
+ html {
+ padding: 30px 10px;
+ font-size: 20px;
+ line-height: 1.4;
+ color: #737373;
+ background: #f0f0f0;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+ }
+
+ html,
+ input {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ }
+
+ body {
+ max-width: 500px;
+ padding: 30px 20px 50px;
+ border: 1px solid #b3b3b3;
+ border-radius: 4px;
+ margin: 0 auto;
+ box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
+ background: #fcfcfc;
+ }
+
+ h1 {
+ margin: 0 10px;
+ font-size: 50px;
+ text-align: center;
+ }
+
+ h1 span {
+ color: #bbb;
+ }
+
+ h3 {
+ margin: 1.5em 0 0.5em;
+ }
+
+ p {
+ margin: 1em 0;
+ }
+
+ ul {
+ padding: 0 0 0 40px;
+ margin: 1em 0;
+ }
+
+ .container {
+ max-width: 380px;
+ margin: 0 auto;
+ }
+
+ /* google search */
+
+ #goog-fixurl ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ }
+
+ #goog-fixurl form {
+ margin: 0;
+ }
+
+ #goog-wm-qt,
+ #goog-wm-sb {
+ border: 1px solid #bbb;
+ font-size: 16px;
+ line-height: normal;
+ vertical-align: top;
+ color: #444;
+ border-radius: 2px;
+ }
+
+ #goog-wm-qt {
+ width: 220px;
+ height: 20px;
+ padding: 5px;
+ margin: 5px 10px 0 0;
+ box-shadow: inset 0 1px 1px #ccc;
+ }
+
+ #goog-wm-sb {
+ display: inline-block;
+ height: 32px;
+ padding: 0 10px;
+ margin: 5px 0 0;
+ white-space: nowrap;
+ cursor: pointer;
+ background-color: #f5f5f5;
+ background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+ background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+ background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+ background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ }
+
+ #goog-wm-sb:hover,
+ #goog-wm-sb:focus {
+ border-color: #aaa;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ background-color: #f8f8f8;
+ }
+
+ #goog-wm-qt:hover,
+ #goog-wm-qt:focus {
+ border-color: #105cb6;
+ outline: 0;
+ color: #222;
+ }
+
+ input::-moz-focus-inner {
+ padding: 0;
+ border: 0;
+ }
+ </style>
+ </head>
+ <body>
+ <div class="container">
+ <h1>Not found <span>:(</span></h1>
+ <p>Sorry, but the page you were trying to view does not exist.</p>
+ <p>It looks like this was the result of either:</p>
+ <ul>
+ <li>a mistyped address</li>
+ <li>an out-of-date link</li>
+ </ul>
+ <script>
+ var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;
+ </script>
+ <script src="//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
+ </div>
+ </body>
+</html>
diff --git a/gui/app/favicon.ico b/gui/app/favicon.ico
new file mode 100644
index 000000000..652790530
--- /dev/null
+++ b/gui/app/favicon.ico
Binary files differ
diff --git a/gui/app/images/back.png b/gui/app/images/back.png
new file mode 100644
index 000000000..917c86edd
--- /dev/null
+++ b/gui/app/images/back.png
Binary files differ
diff --git a/gui/app/images/checkno.png b/gui/app/images/checkno.png
new file mode 100644
index 000000000..7c6841930
--- /dev/null
+++ b/gui/app/images/checkno.png
Binary files differ
diff --git a/gui/app/images/checkyes.png b/gui/app/images/checkyes.png
new file mode 100644
index 000000000..ef6028310
--- /dev/null
+++ b/gui/app/images/checkyes.png
Binary files differ
diff --git a/gui/app/images/close.png b/gui/app/images/close.png
new file mode 100644
index 000000000..0d2c14252
--- /dev/null
+++ b/gui/app/images/close.png
Binary files differ
diff --git a/gui/app/images/loading.gif b/gui/app/images/loading.gif
new file mode 100644
index 000000000..b04dd11bc
--- /dev/null
+++ b/gui/app/images/loading.gif
Binary files differ
diff --git a/gui/app/images/loading2.gif b/gui/app/images/loading2.gif
new file mode 100644
index 000000000..9d1534468
--- /dev/null
+++ b/gui/app/images/loading2.gif
Binary files differ
diff --git a/gui/app/images/statusno.png b/gui/app/images/statusno.png
new file mode 100644
index 000000000..ace4a454d
--- /dev/null
+++ b/gui/app/images/statusno.png
Binary files differ
diff --git a/gui/app/images/statusyes.png b/gui/app/images/statusyes.png
new file mode 100644
index 000000000..d88a99ee8
--- /dev/null
+++ b/gui/app/images/statusyes.png
Binary files differ
diff --git a/gui/app/images/url.json b/gui/app/images/url.json
new file mode 100644
index 000000000..f16c4e0ac
--- /dev/null
+++ b/gui/app/images/url.json
@@ -0,0 +1 @@
+{"url": "192.168.23.2:1948"} \ No newline at end of file
diff --git a/gui/app/images/yeoman.png b/gui/app/images/yeoman.png
new file mode 100644
index 000000000..92497addf
--- /dev/null
+++ b/gui/app/images/yeoman.png
Binary files differ
diff --git a/gui/app/index.html b/gui/app/index.html
new file mode 100644
index 000000000..5592656cc
--- /dev/null
+++ b/gui/app/index.html
@@ -0,0 +1,111 @@
+<!doctype html>
+<html>
+
+<head>
+ <meta charset="utf-8">
+ <title></title>
+ <meta name="description" content="">
+ <meta name="viewport" content="width=device-width">
+ <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
+ <!-- build:css(.) styles/vendor.css -->
+ <!-- bower:css -->
+ <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
+ <link rel="stylesheet" href="bower_components/angular-wizard/dist/angular-wizard.min.css" />
+ <link rel="stylesheet" href="bower_components/AngularJS-Toaster/toaster.css" />
+ <link rel="stylesheet" href="bower_components/ng-dialog/css/ngDialog.css" />
+ <link rel="stylesheet" href="bower_components/ng-dialog/css/ngDialog-theme-default.css" />
+ <link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.css" />
+ <link rel="stylesheet" href="bower_components/v-accordion/dist/v-accordion.css" />
+ <link rel="stylesheet" href="bower_components/angular-loading/angular-loading.css" />
+ <!-- endbower -->
+ <!-- endbuild -->
+ <!-- build:css(.tmp) styles/main.css -->
+ <link rel="stylesheet" href="styles/main.css">
+
+
+ <!-- endbuild -->
+</head>
+
+<script>
+// read file
+
+
+</script>
+
+<body ng-app="yardStickGui2App">
+ <!--[if lte IE 8]>
+ <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
+ <![endif]-->
+
+
+
+
+ <div ui-view></div>
+
+
+
+
+ <!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
+ <!--<script>
+ ! function(A, n, g, u, l, a, r) {
+ A.GoogleAnalyticsObject = l, A[l] = A[l] || function() {
+ (A[l].q = A[l].q || []).push(arguments)
+ }, A[l].l = +new Date, a = n.createElement(g),
+ r = n.getElementsByTagName(g)[0], a.src = u, r.parentNode.insertBefore(a, r)
+ }(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
+
+ ga('create', 'UA-XXXXX-X');
+ ga('send', 'pageview');
+ </script>-->
+
+ <!-- build:js(.) scripts/vendor.js -->
+ <!-- bower:js -->
+ <script src="bower_components/jquery/dist/jquery.js"></script>
+ <script src="bower_components/angular/angular.js"></script>
+ <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
+ <script src="bower_components/angular-strap/dist/angular-strap.js"></script>
+ <script src="bower_components/angular-strap/dist/angular-strap.tpl.js"></script>
+ <script src="bower_components/angular-ui-router/release/angular-ui-router.js"></script>
+ <script src="bower_components/angular-animate/angular-animate.js"></script>
+ <script src="bower_components/angular-breadcrumb/release/angular-breadcrumb.js"></script>
+ <script src="bower_components/angular-wizard/dist/angular-wizard.min.js"></script>
+ <script src="bower_components/angular-resource/angular-resource.js"></script>
+ <script src="bower_components/ng-file-upload/ng-file-upload.js"></script>
+ <script src="bower_components/AngularJS-Toaster/toaster.js"></script>
+ <script src="bower_components/ng-dialog/js/ngDialog.js"></script>
+ <script src="bower_components/angularUtils-pagination/dirPagination.js"></script>
+ <script src="bower_components/ngstorage/ngStorage.js"></script>
+ <script src="bower_components/v-accordion/dist/v-accordion.js"></script>
+ <script src="bower_components/spin.js/spin.js"></script>
+ <script src="bower_components/angular-loading/angular-loading.js"></script>
+ <script src="bower_components/spin.js/spin.js"></script>
+ <script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
+ <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
+ <!-- endbower -->
+ <!-- endbuild -->
+
+ <!-- build:js({.tmp,app}) scripts/scripts.js -->
+ <script src="scripts/app.js"></script>
+ <script src="scripts/router.config.js"></script>
+ <script src="scripts/controllers/main.js"></script>
+ <script src="scripts/factory/main.factory.js"></script>
+ <script src="scripts/controllers/content.controller.js"></script>
+ <script src="scripts/controllers/detail.controller.js"></script>
+ <script src="scripts/controllers/image.controller.js"></script>
+ <script src="scripts/controllers/pod.controller.js"></script>
+ <script src="scripts/controllers/container.controller.js"></script>
+ <script src="scripts/controllers/testcase.controller.js"></script>
+ <script src="scripts/controllers/testcasedetail.controller.js"></script>
+ <script src="scripts/controllers/testsuit.controller.js"></script>
+ <script src="scripts/controllers/suitedetail.controller.js"></script>
+ <script src="scripts/controllers/suitecreate.controller.js"></script>
+ <script src="scripts/controllers/task.controller.js"></script>
+ <script src="scripts/controllers/report.controller.js"></script>
+ <script src="scripts/controllers/project.controller.js"></script>
+ <script src="scripts/controllers/projectDetail.controller.js"></script>
+ <script src="scripts/controllers/taskModify.controller.js"></script>
+
+ <!-- endbuild -->
+</body>
+
+</html>
diff --git a/gui/app/robots.txt b/gui/app/robots.txt
new file mode 100644
index 000000000..4d521f952
--- /dev/null
+++ b/gui/app/robots.txt
@@ -0,0 +1,4 @@
+# robotstxt.org
+
+User-agent: *
+Disallow:
diff --git a/gui/app/scripts/app.js b/gui/app/scripts/app.js
new file mode 100644
index 000000000..ecb642c95
--- /dev/null
+++ b/gui/app/scripts/app.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ * @ngdoc overview
+ * @name yardStickGui2App
+ * @description
+ * # yardStickGui2App
+ *
+ * Main module of the application.
+ */
+angular
+ .module('yardStickGui2App', [
+ 'ui.router',
+ 'ngAnimate',
+ 'ngSanitize',
+ 'mgcrea.ngStrap',
+ 'ncy-angular-breadcrumb',
+ 'mgo-angular-wizard',
+ 'ngResource',
+ 'ngFileUpload',
+ 'toaster',
+ 'ngDialog',
+ 'angularUtils.directives.dirPagination',
+ 'ngStorage',
+ 'vAccordion',
+ 'darthwade.dwLoading',
+ 'ui.bootstrap'
+
+
+ ]);
diff --git a/gui/app/scripts/controllers/container.controller.js b/gui/app/scripts/controllers/container.controller.js
new file mode 100644
index 000000000..6c2ccd8ff
--- /dev/null
+++ b/gui/app/scripts/controllers/container.controller.js
@@ -0,0 +1,182 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('ContainerController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog) {
+
+
+ init();
+ $scope.showloading = false;
+
+ $scope.displayContainerInfo = [];
+ $scope.containerList = [{ value: 'create_influxdb', name: "InfluxDB" }, { value: 'create_grafana', name: "Grafana" }]
+
+ function init() {
+
+
+ $scope.uuid = $stateParams.uuid;
+ $scope.createContainer = createContainer;
+ $scope.openChooseContainnerDialog = openChooseContainnerDialog;
+
+
+ getItemIdDetail();
+
+ }
+
+ function getItemIdDetail() {
+ $scope.displayContainerInfo = [];
+ mainFactory.ItemDetail().get({
+ 'envId': $scope.uuid
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.envName = response.result.environment.name;
+ $scope.containerId = response.result.environment.container_id;
+ if ($scope.containerId != null) {
+
+ var keysArray = Object.keys($scope.containerId);
+ for (var k in $scope.containerId) {
+ getConDetail($scope.containerId[k]);
+ }
+ } else {
+ $scope.podData = null;
+ }
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getConDetail(id) {
+ mainFactory.containerDetail().get({
+ 'containerId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ // $scope.podData = response.result;
+ response.result.container['id'] = id;
+ $scope.displayContainerInfo.push(response.result.container);
+
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+
+ }
+
+ function createContainer() {
+
+ $scope.showloading = true;
+ mainFactory.runAcontainer().post({
+ 'action': $scope.selectContainer.value,
+ 'args': {
+ 'environment_id': $scope.uuid,
+ }
+ }).$promise.then(function(response) {
+ $scope.showloading = false;
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create container success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ setTimeout(function() {
+ getItemIdDetail();
+ }, 10000);
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function openChooseContainnerDialog() {
+ ngDialog.open({
+ template: 'views/modal/chooseContainer.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+ }
+
+ function chooseResult(name) {
+ $scope.selectContainer = name;
+ }
+ $scope.goBack = function goBack() {
+ $state.go('app2.projectList');
+ }
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteContainer = function deleteContainer() {
+ mainFactory.deleteContainer().delete({ 'containerId': $scope.deleteId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete container success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getItemIdDetail();
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/content.controller.js b/gui/app/scripts/controllers/content.controller.js
new file mode 100644
index 000000000..d2bc19eea
--- /dev/null
+++ b/gui/app/scripts/controllers/content.controller.js
@@ -0,0 +1,136 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('ContentController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', '$location', '$localStorage',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, $location, $localStorage) {
+
+
+
+
+ init();
+ $scope.showEnvironment = false;
+ $scope.counldGoDetail = false;
+ $scope.activeStatus = 0;
+
+ $scope.$watch(function() {
+ return location.hash
+ }, function(newvalue, oldvalue) {
+ if (location.hash.indexOf('project') > -1) {
+ $scope.projectShow = true;
+ $scope.taskShow = false;
+ $scope.reportShow = false;
+ } else if (location.hash.indexOf('task') > -1) {
+ $scope.taskShow = true;
+ $scope.projectShow = true;
+ } else if (location.hash.indexOf('report') > -1) {
+ $scope.reportShow = true;
+ $scope.taskShow = true;
+ $scope.projectShow = true;
+ }
+
+ })
+
+
+ function init() {
+
+
+ $scope.showEnvironments = showEnvironments;
+ $scope.showSteps = $location.path().indexOf('project');
+ $scope.test = test;
+ $scope.gotoUploadPage = gotoUploadPage;
+ $scope.gotoOpenrcPage = gotoOpenrcPage;
+ $scope.gotoPodPage = gotoPodPage;
+ $scope.gotoContainerPage = gotoContainerPage;
+ $scope.gotoTestcase = gotoTestcase;
+ $scope.gotoEnviron = gotoEnviron;
+ $scope.gotoSuite = gotoSuite;
+ $scope.gotoProject = gotoProject;
+ $scope.gotoTask = gotoTask;
+ $scope.gotoReport = gotoReport;
+ $scope.stepsStatus = $localStorage.stepsStatus;
+ $scope.goBack = goBack;
+
+
+ }
+
+
+
+ function showEnvironments() {
+ $scope.showEnvironment = true;
+ }
+
+ function test() {
+ alert('test');
+ }
+
+ function gotoOpenrcPage() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.environmentDetail', { uuid: $scope.uuid })
+ }
+
+ function gotoUploadPage() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.uploadImage', { uuid: $scope.uuid });
+ }
+
+ function gotoPodPage() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.podUpload', { uuid: $scope.uuid });
+ }
+
+ function gotoContainerPage() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.container', { uuid: $scope.uuid });
+ }
+
+ function gotoTestcase() {
+ $state.go('app2.testcase');
+ }
+
+ function gotoEnviron() {
+ if ($location.path().indexOf('env') > -1 || $location.path().indexOf('environment') > -1) {
+ $scope.counldGoDetail = true;
+ }
+ $state.go('app2.environment');
+ }
+
+ function gotoSuite() {
+ $state.go('app2.testsuite');
+ }
+
+ function gotoProject() {
+ $state.go('app2.projectList');
+ }
+
+ function gotoTask() {
+ $state.go('app2.tasklist');
+ }
+
+ function gotoReport() {
+ $state.go('app2.report');
+ }
+
+ function goBack() {
+ if ($location.path().indexOf('main/environment')) {
+ return;
+ } else if ($location.path().indexOf('main/envDetail/') || $location.path().indexOf('main/imageDetail/') ||
+ $location.path().indexOf('main/podupload/') || $location.path().indexOf('main/container/')) {
+ $state.go('app2.environment');
+ return;
+ } else {
+ window.history.back();
+ }
+
+ }
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/detail.controller.js b/gui/app/scripts/controllers/detail.controller.js
new file mode 100644
index 000000000..3e2eaa100
--- /dev/null
+++ b/gui/app/scripts/controllers/detail.controller.js
@@ -0,0 +1,384 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('DetailController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', '$location', 'ngDialog',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, $location, ngDialog) {
+
+
+
+
+ init();
+ $scope.showEnvironment = false;
+ $scope.envInfo = [];
+
+ function init() {
+ $scope.showEnvironments = showEnvironments;
+ // $scope.openrcID = $stateParams.uuid;
+ $scope.deleteEnvItem = deleteEnvItem;
+ $scope.addInfo = addInfo;
+ $scope.submitOpenRcFile = submitOpenRcFile;
+ $scope.uploadFiles = uploadFiles;
+ $scope.addEnvironment = addEnvironment;
+
+ $scope.uuid = $stateParams.uuid;
+ $scope.openrcID = $stateParams.opercId;
+ $scope.imageID = $stateParams.imageId;
+ $scope.podID = $stateParams.podId;
+ $scope.containerId = $stateParams.containerId;
+ $scope.ifNew = $stateParams.ifNew;
+
+
+ getItemIdDetail();
+ }
+
+
+
+ function showEnvironments() {
+ $scope.showEnvironment = true;
+ }
+
+
+ function deleteEnvItem(index) {
+ $scope.envInfo.splice(index, 1);
+ }
+
+ function addInfo() {
+ var tempKey = null;
+ var tempValue = null;
+ var temp = {
+ name: tempKey,
+ value: tempValue
+ }
+ $scope.envInfo.push(temp);
+
+ }
+
+ function submitOpenRcFile() {
+ $scope.showloading = true;
+
+ var postData = {};
+ postData['action'] = 'update_openrc';
+ rebuildEnvInfo();
+ postData['args'] = {};
+ postData['args']['openrc'] = $scope.postEnvInfo;
+ postData['args']['environment_id'] = $scope.uuid;
+
+
+ mainFactory.postEnvironmentVariable().post(postData).$promise.then(function(response) {
+ $scope.showloading = false;
+
+ if (response.status == 1) {
+
+ $scope.openrcInfo = response.result;
+ toaster.pop({
+ type: 'success',
+ title: 'create success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.showEnvrionment = true;
+ getItemIdDetail();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'faile',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //reconstruc EnvInfo
+ function rebuildEnvInfo() {
+ $scope.postEnvInfo = {};
+ for (var i = 0; i < $scope.envInfo.length; i++) {
+ $scope.postEnvInfo[$scope.envInfo[i].name] = $scope.envInfo[i].value;
+ }
+
+ }
+
+ //buildtoEnvInfo
+ function buildToEnvInfo(object) {
+ var tempKeyArray = Object.keys(object);
+
+ for (var i = 0; i < tempKeyArray.length; i++) {
+ var tempkey = tempKeyArray[i];
+ var tempValue = object[tempKeyArray[i]];
+ var temp = {
+ name: tempkey,
+ value: tempValue
+ };
+ $scope.envInfo.push(temp);
+ }
+ }
+
+ function uploadFiles($file, $invalidFiles) {
+ $scope.openrcInfo = {};
+ $scope.loadingOPENrc = true;
+
+ $scope.displayOpenrcFile = $file;
+ timeConstruct($scope.displayOpenrcFile.lastModified);
+ Upload.upload({
+ url: Base_URL + '/api/v2/yardstick/openrcs',
+ data: { file: $file, 'environment_id': $scope.uuid, 'action': 'upload_openrc' }
+ }).then(function(response) {
+
+ $scope.loadingOPENrc = false;
+ if (response.data.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'upload success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.openrcInfo = response.data.result;
+ getItemIdDetail();
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'faile',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ $scope.uploadfile = null;
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function timeConstruct(array) {
+ var date = new Date(1398250549490);
+ var Y = date.getFullYear() + '-';
+ var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+ var D = date.getDate() + ' ';
+ var h = date.getHours() + ':';
+ var m = date.getMinutes() + ':';
+ var s = date.getSeconds();
+ $scope.filelastModified = Y + M + D + h + m + s;
+
+ }
+
+ function addEnvironment() {
+ mainFactory.addEnvName().post({
+ 'action': 'create_environment',
+ args: {
+ 'name': $scope.baseElementInfo.name
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create name success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.uuid = response.result.uuid;
+ var path = $location.path();
+ path = path + $scope.uuid;
+ $location.url(path);
+ getItemIdDetail();
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getItemIdDetail() {
+
+ mainFactory.ItemDetail().get({
+ 'envId': $scope.uuid
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.baseElementInfo = response.result.environment;
+
+
+ if ($scope.ifNew != 'true') {
+ $scope.baseElementInfo = response.result.environment;
+ if ($scope.baseElementInfo.openrc_id != null) {
+ getOpenrcDetail($scope.baseElementInfo.openrc_id);
+ }
+ }
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+ //getopenRcid
+ function getOpenrcDetail(openrcId) {
+ mainFactory.getEnvironmentDetail().get({
+ 'openrc_id': openrcId
+ }).$promise.then(function(response) {
+ $scope.openrcInfo = response.result;
+ buildToEnvInfo($scope.openrcInfo.openrc)
+ }, function(response) {
+
+ })
+ }
+
+
+ //getImgDetail
+ function getImageDetail() {
+ mainFactory.ImageDetail().get({
+ 'image_id': $scope.baseElementInfo.image_id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageDetail = response.result.image;
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //getPodDetail
+ function getPodDetail() {
+ mainFactory.podDeatil().get({
+ 'podId': $scope.baseElementInfo.pod_id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.podDetail = response.result.pod;
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+ //getContainerDetail
+ function getPodDetail(containerId) {
+ mainFactory.containerDetail().get({
+ 'containerId': containerId
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.podDetail = response.result.pod;
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+ $scope.goBack = function goBack() {
+ window.history.back();
+ }
+
+ $scope.goNext = function goNext() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.uploadImage', { uuid: $scope.uuid });
+ }
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteOpenRc = function deleteOpenRc() {
+ mainFactory.deleteOpenrc().delete({ 'openrc': $scope.baseElementInfo.openrc_id }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete openrc success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getItemIdDetail();
+ $scope.openrcInfo = null;
+ $scope.envInfo = [];
+ $scope.displayOpenrcFile = null;
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+
+
+
+
+
+
+ }
+
+
+ ]);
diff --git a/gui/app/scripts/controllers/image.controller.js b/gui/app/scripts/controllers/image.controller.js
new file mode 100644
index 000000000..53acff405
--- /dev/null
+++ b/gui/app/scripts/controllers/image.controller.js
@@ -0,0 +1,166 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('ImageController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', '$location', '$interval',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, $location, $interval) {
+
+
+ init();
+ $scope.showloading = false;
+ $scope.ifshowStatus = 0;
+
+ function init() {
+
+
+ $scope.uuid = $stateParams.uuid;
+ $scope.uploadImage = uploadImage;
+ getItemIdDetail();
+ getImageListSimple();
+ }
+
+ function getItemIdDetail() {
+ mainFactory.ItemDetail().get({
+ 'envId': $stateParams.uuid
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.baseElementInfo = response.result.environment;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getImageListSimple() {
+
+ mainFactory.ImageList().get({}).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageListData = response.result.images;
+ // $scope.imageStatus = response.result.status;
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function getImageList() {
+ if ($scope.intervalImgae != undefined) {
+ $interval.cancel($scope.intervalImgae);
+ }
+ mainFactory.ImageList().get({}).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageListData = response.result.images;
+ $scope.imageStatus = response.result.status;
+
+ if ($scope.imageStatus == 0) {
+ $scope.intervalImgae = $interval(function() {
+ getImageList();
+ }, 5000);
+ } else if ($scope.intervalImgae != undefined) {
+ $interval.cancel($scope.intervalImgae);
+ }
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ })
+ }
+
+ function uploadImage() {
+ $scope.imageStatus = 0;
+ $interval.cancel($scope.intervalImgae);
+ $scope.ifshowStatus = 1;
+ $scope.showloading = true;
+ mainFactory.uploadImage().post({
+ 'action': 'load_image',
+ 'args': {
+ 'environment_id': $scope.uuid
+
+ }
+ }).$promise.then(function(response) {
+ $scope.showloading = false;
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ setTimeout(function() {
+ getImageList();
+ }, 10000);
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'failed',
+ body: 'something wrong',
+ timeout: 3000
+ });
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'failed',
+ body: 'something wrong',
+ timeout: 3000
+ });
+ })
+ }
+
+ $scope.goBack = function goBack() {
+ $state.go('app2.projectList');
+ }
+
+ $scope.goNext = function goNext() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.podUpload', { uuid: $scope.uuid });
+ }
+
+
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/main.js b/gui/app/scripts/controllers/main.js
new file mode 100644
index 000000000..e3e880e62
--- /dev/null
+++ b/gui/app/scripts/controllers/main.js
@@ -0,0 +1,725 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('MainCtrl', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog', '$localStorage', '$loading', '$interval',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog, $localStorage, $loading, $interval) {
+
+
+ init();
+ $scope.project = 0;
+ $scope.showloading = false;
+ $scope.showEnvrionment = false;
+ $scope.loadingOPENrc = false;
+ $scope.uuidEnv = null;
+ $scope.showPod = null;
+ $scope.showImage = null;
+ $scope.showContainer = null;
+ $scope.showNextOpenRc = null;
+ $scope.showNextPod = null;
+ $scope.displayContainerInfo = [];
+ $scope.containerList = [{ value: 'create_influxdb', name: "InfluxDB" }, { value: 'create_grafana', name: "Grafana" }]
+ $scope.items = [
+ 'The first choice!',
+ 'And another choice for you.',
+ 'but wait! A third!'
+ ];
+ $scope.$on('$destroy', function() {
+ $interval.cancel($scope.intervalImgae)
+ });
+ $scope.showImageStatus = 0;
+
+
+
+
+
+
+ function init() {
+
+
+ $scope.gotoProject = gotoProject;
+ $scope.gotoEnvironment = gotoEnvironment;
+ $scope.gotoTask = gotoTask;
+ $scope.gotoExcute = gotoExcute;
+ $scope.gotoReport = gotoReport;
+ $scope.deleteEnvItem = deleteEnvItem;
+ $scope.addInfo = addInfo;
+ $scope.submitOpenRcFile = submitOpenRcFile;
+ $scope.uploadFilesPod = uploadFilesPod;
+ $scope.uploadFiles = uploadFiles;
+ $scope.showEnvriomentStatus = showEnvriomentStatus;
+ $scope.openEnvironmentDialog = openEnvironmentDialog;
+ $scope.getEnvironmentList = getEnvironmentList;
+ $scope.gotoDetail = gotoDetail;
+ $scope.addEnvironment = addEnvironment;
+ $scope.createContainer = createContainer;
+ $scope.chooseResult = chooseResult;
+
+ getEnvironmentList();
+ // getImageList();
+
+ }
+
+ function gotoProject() {
+ $scope.project = 1;
+ }
+
+ function gotoEnvironment() {
+ $scope.project = 0;
+ }
+
+ function gotoTask() {
+ $scope.project = 2;
+ }
+
+ function gotoExcute() {
+ $scope.project = 3;
+
+ }
+
+ function gotoReport() {
+ $scope.project = 4;
+ }
+ $scope.skipPod = function skipPod() {
+ $scope.showContainer = 1;
+
+ }
+ $scope.skipContainer = function skipContainer() {
+ getEnvironmentList();
+ ngDialog.close();
+ }
+
+ $scope.goToImage = function goToImage() {
+ getImageListSimple();
+ $scope.showImage = 1;
+ }
+ $scope.goToPod = function goToPod() {
+ $scope.showPod = 1;
+ }
+ $scope.goToPodPrev = function goToPodPrev() {
+ $scope.showImage = null;
+
+ }
+ $scope.skipPodPrev = function skipPodPrev() {
+ $scope.showImage = 1;
+ $scope.showPod = null;
+
+ }
+ $scope.skipContainerPrev = function skipContainerPrev() {
+ $scope.showPod = 1;
+ $scope.showContainer = null;
+ }
+
+ $scope.envInfo = [
+ { name: 'OS_USERNAME', value: '' },
+ { name: 'OS_PASSWORD', value: '' },
+ { name: 'OS_TENANT_NAME', value: '' },
+ { name: 'EXTERNAL_NETWORK', value: '' }
+ ];
+
+
+ function deleteEnvItem(index) {
+ $scope.envInfo.splice(index, 1);
+ }
+
+ function addInfo() {
+ var tempKey = null;
+ var tempValue = null;
+ var temp = {
+ name: tempKey,
+ value: tempValue
+ }
+ $scope.envInfo.push(temp);
+
+ }
+
+ function submitOpenRcFile() {
+ $scope.showloading = true;
+
+ var postData = {};
+ postData['action'] = 'update_openrc';
+ rebuildEnvInfo();
+ postData['args'] = {};
+ postData.args["openrc"] = $scope.postEnvInfo;
+ postData.args['environment_id'] = $scope.uuidEnv;
+ mainFactory.postEnvironmentVariable().post(postData).$promise.then(function(response) {
+ $scope.showloading = false;
+
+ if (response.status == 1) {
+
+ $scope.openrcInfo = response.result;
+ toaster.pop({
+ type: 'success',
+ title: 'create success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.showEnvrionment = true;
+ // $scope.showImage = response.status;
+ $scope.showNextOpenRc = 1;
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function uploadFiles($file, $invalidFiles) {
+ $scope.openrcInfo = {};
+ $scope.loadingOPENrc = true;
+ $scope.displayOpenrcFile = $file;
+ timeConstruct($scope.displayOpenrcFile.lastModified);
+ Upload.upload({
+ url: Base_URL + '/api/v2/yardstick/openrcs',
+ data: { file: $file, 'environment_id': $scope.uuidEnv, 'action': 'upload_openrc' }
+ }).then(function(response) {
+
+ $scope.loadingOPENrc = false;
+ if (response.data.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'upload success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.openrcInfo = response.data.result;
+
+ getItemIdDetailforOpenrc();
+ $scope.showNextOpenRc = 1;
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ $scope.uploadfile = null;
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //reconstruc EnvInfo
+ function rebuildEnvInfo() {
+ $scope.postEnvInfo = {};
+ for (var i = 0; i < $scope.envInfo.length; i++) {
+ $scope.postEnvInfo[$scope.envInfo[i].name] = $scope.envInfo[i].value;
+ }
+
+ }
+ function uploadFilesPod($file, $invalidFiles) {
+ $scope.loadingOPENrc = true;
+
+ $scope.displayPodFile = $file;
+ timeConstruct($scope.displayPodFile.lastModified);
+ Upload.upload({
+ url: Base_URL + '/api/v2/yardstick/pods',
+ data: { file: $file, 'environment_id': $scope.uuidEnv, 'action': 'upload_pod_file' }
+ }).then(function(response) {
+
+ $scope.loadingOPENrc = false;
+ if (response.data.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'upload success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+
+ $scope.podData = response.data.result;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ $scope.uploadfile = null;
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function timeConstruct(array) {
+ var date = new Date(1398250549490);
+ var Y = date.getFullYear() + '-';
+ var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+ var D = date.getDate() + ' ';
+ var h = date.getHours() + ':';
+ var m = date.getMinutes() + ':';
+ var s = date.getSeconds();
+ $scope.filelastModified = Y + M + D + h + m + s;
+
+ }
+
+ //display environment
+ function showEnvriomentStatus() {
+ $scope.showEnvironment = true;
+ }
+
+ //open Environment dialog
+ function openEnvironmentDialog() {
+ $scope.showEnvrionment = false;
+ $scope.loadingOPENrc = false;
+ $scope.uuidEnv = null;
+ $scope.showPod = null;
+ $scope.showImage = null;
+ $scope.showContainer = null;
+ $scope.showNextOpenRc = null;
+ $scope.showNextPod = null;
+ $scope.displayContainerInfo = [];
+
+ $scope.displayPodFile = null;
+ $scope.name = null;
+ $scope.openrcInfo = null;
+ $scope.envInfo = [
+ { name: 'OS_USERNAME', value: '' },
+ { name: 'OS_PASSWORD', value: '' },
+ { name: 'OS_TENANT_NAME', value: '' },
+ { name: 'EXTERNAL_NETWORK', value: '' }
+ ];
+ $scope.displayOpenrcFile = null;
+ $scope.podData = null;
+ $scope.displayContainerInfo = null;
+ ngDialog.open({
+ preCloseCallback: function(value) {
+ getEnvironmentList();
+ // getImageList();
+ },
+ template: 'views/modal/environmentDialog.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 950,
+ showClose: true,
+ closeByDocument: false
+ })
+ }
+
+ function getEnvironmentList() {
+ $loading.start('key');
+
+ mainFactory.getEnvironmentList().get().$promise.then(function(response) {
+ $scope.environmentList = response.result.environments;
+ $loading.finish('key');
+
+ }, function(error) {
+ $loading.finish('key');
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ //go to detail page
+ function gotoDetail(ifNew, uuid) {
+
+ $state.go('app.environmentDetail', { uuid: uuid, ifNew: ifNew });
+ }
+
+
+ function addEnvironment(name) {
+ mainFactory.addEnvName().post({
+ 'action': 'create_environment',
+ args: {
+ 'name': name
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create name success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.uuidEnv = response.result.uuid;
+ $scope.name = name;
+
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+ $scope.goBack = function goBack() {
+ $state.go('app2.projectList');
+ }
+ $scope.displayContainerInfo = [];
+
+ function createContainer(selectContainer) {
+
+ $scope.showloading = true;
+ mainFactory.runAcontainer().post({
+ 'action': selectContainer.value,
+ 'args': {
+ 'environment_id': $scope.uuidEnv,
+ }
+ }).$promise.then(function(response) {
+ $scope.showloading = false;
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create container success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+
+ setTimeout(function() {
+ getItemIdDetail();
+ }, 10000);
+ $scope.ifskipOrClose = 1;
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getConDetail(id) {
+ mainFactory.containerDetail().get({
+ 'containerId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ // $scope.podData = response.result;
+ $scope.displayContainerInfo.push(response.result.container);
+
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+
+ }
+
+ function chooseResult(name) {
+ $scope.selectContainer = name;
+ }
+
+ function getItemIdDetail() {
+ $scope.displayContainerInfo = [];
+ mainFactory.ItemDetail().get({
+ 'envId': $scope.uuidEnv
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.envName = response.result.environment.name;
+ $scope.containerId = response.result.environment.container_id;
+ if ($scope.containerId != null) {
+
+ var keysArray = Object.keys($scope.containerId);
+ for (var k in $scope.containerId) {
+ getConDetail($scope.containerId[k]);
+
+ }
+
+
+ } else {
+ $scope.podData = null;
+ }
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ $scope.uploadImage = function uploadImage() {
+ $scope.imageStatus = 0;
+ $scope.showImageStatus = 1;
+ $scope.showloading = true;
+ mainFactory.uploadImage().post({
+ 'action': 'load_image',
+ 'args': {
+ 'environment_id': $scope.uuid
+
+ }
+ }).$promise.then(function(response) {
+ $scope.showloading = false;
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ setTimeout(function() {
+ getImageList();
+ }, 10000);
+ $scope.showNextPod = 1;
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'failed',
+ body: 'something wrong',
+ timeout: 3000
+ });
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'failed',
+ body: 'something wrong',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getImageList() {
+ if ($scope.intervalImgae != undefined) {
+ $interval.cancel($scope.intervalImgae);
+ }
+ mainFactory.ImageList().get({}).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageListData = response.result.images;
+ $scope.imageStatus = response.result.status;
+
+ if ($scope.imageStatus == 0) {
+ $scope.intervalImgae = $interval(function() {
+ getImageList();
+ }, 5000);
+ } else if ($scope.intervalImgae != undefined) {
+ $interval.cancel($scope.intervalImgae);
+ }
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getImageListSimple() {
+
+ mainFactory.ImageList().get({}).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageListData = response.result.images;
+ $scope.imageStatus = response.result.status;
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'get data failed',
+ body: 'please retry',
+ timeout: 3000
+ });
+ })
+ }
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteEnv = function deleteEnv() {
+ mainFactory.deleteEnv().delete({ 'env_id': $scope.deleteId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete environment success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getEnvironmentList();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+
+
+
+ function getItemIdDetailforOpenrc() {
+
+ mainFactory.ItemDetail().get({
+ 'envId': $scope.uuidEnv
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.baseElementInfo = response.result.environment;
+
+
+ if ($scope.ifNew != 'true') {
+ $scope.baseElementInfo = response.result.environment;
+ if ($scope.baseElementInfo.openrc_id != null) {
+ getOpenrcDetailForOpenrc($scope.baseElementInfo.openrc_id);
+ }
+ }
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+
+ }
+ }, function(error) {
+
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+
+
+ //getopenRcid
+ function getOpenrcDetailForOpenrc(openrcId) {
+ mainFactory.getEnvironmentDetail().get({
+ 'openrc_id': openrcId
+ }).$promise.then(function(response) {
+ $scope.openrcInfo = response.result;
+ buildToEnvInfoOpenrc($scope.openrcInfo.openrc)
+ }, function(response) {
+ toaster.pop({
+ type: 'error',
+ title: 'error',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //buildtoEnvInfo
+ function buildToEnvInfoOpenrc(object) {
+ var tempKeyArray = Object.keys(object);
+ $scope.envInfo = [];
+
+
+ for (var i = 0; i < tempKeyArray.length; i++) {
+ var tempkey = tempKeyArray[i];
+ var tempValue = object[tempKeyArray[i]];
+ var temp = {
+ name: tempkey,
+ value: tempValue
+ };
+ $scope.envInfo.push(temp);
+ }
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/pod.controller.js b/gui/app/scripts/controllers/pod.controller.js
new file mode 100644
index 000000000..3ef236854
--- /dev/null
+++ b/gui/app/scripts/controllers/pod.controller.js
@@ -0,0 +1,179 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('PodController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', '$location', 'ngDialog',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, $location, ngDialog) {
+
+
+ init();
+ $scope.showloading = false;
+ $scope.loadingOPENrc = false;
+
+ function init() {
+
+
+ $scope.uuid = $stateParams.uuid;
+ $scope.uploadFiles = uploadFiles;
+ getItemIdDetail();
+
+ }
+
+ function getItemIdDetail() {
+ mainFactory.ItemDetail().get({
+ 'envId': $scope.uuid
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.name = response.result.environment.name;
+ $scope.podId = response.result.environment.pod_id;
+ if ($scope.podId != null) {
+ getPodDetail($scope.podId);
+ } else {
+ $scope.podData = null;
+ }
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getPodDetail(id) {
+ mainFactory.getPodDetail().get({
+ 'podId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.podData = response.result;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+
+ }
+
+ //upload pod file
+ function uploadFiles($file, $invalidFiles) {
+ $scope.loadingOPENrc = true;
+
+ $scope.displayOpenrcFile = $file;
+ timeConstruct($scope.displayOpenrcFile.lastModified);
+ Upload.upload({
+ url: Base_URL + '/api/v2/yardstick/pods',
+ data: { file: $file, 'environment_id': $scope.uuid, 'action': 'upload_pod_file' }
+ }).then(function(response) {
+
+ $scope.loadingOPENrc = false;
+ if (response.data.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'upload success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+
+ $scope.podData = response.data.result;
+
+ getItemIdDetail();
+
+
+ } else {
+
+ }
+
+ }, function(error) {
+ $scope.uploadfile = null;
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function timeConstruct(array) {
+ var date = new Date(1398250549490);
+ var Y = date.getFullYear() + '-';
+ var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+ var D = date.getDate() + ' ';
+ var h = date.getHours() + ':';
+ var m = date.getMinutes() + ':';
+ var s = date.getSeconds();
+ $scope.filelastModified = Y + M + D + h + m + s;
+
+ }
+ $scope.goBack = function goBack() {
+ $state.go('app2.projectList');
+ }
+
+
+ $scope.goNext = function goNext() {
+ $scope.path = $location.path();
+ $scope.uuid = $scope.path.split('/').pop();
+ $state.go('app.container', { uuid: $scope.uuid });
+ }
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deletePod = function deletePod() {
+ mainFactory.deletePod().delete({ 'podId': $scope.podId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete pod success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ $scope.uuid = $stateParams.uuid;
+ $scope.uploadFiles = uploadFiles;
+ $scope.displayOpenrcFile = null;
+ getItemIdDetail();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/project.controller.js b/gui/app/scripts/controllers/project.controller.js
new file mode 100644
index 000000000..0a7b8b932
--- /dev/null
+++ b/gui/app/scripts/controllers/project.controller.js
@@ -0,0 +1,160 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('ProjectController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog', '$loading',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog, $loading) {
+
+
+ init();
+
+
+ function init() {
+
+
+ getProjectList();
+ $scope.openCreateProject = openCreateProject;
+ $scope.createName = createName;
+ $scope.gotoDetail = gotoDetail;
+
+
+ }
+
+ function getProjectList() {
+ $loading.start('key');
+ mainFactory.projectList().get({}).$promise.then(function(response) {
+ $loading.finish('key');
+ if (response.status == 1) {
+ $scope.projectListData = response.result.projects;
+
+
+ } else {
+
+ }
+ }, function(error) {
+ $loading.finish('key');
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function openCreateProject() {
+
+ ngDialog.open({
+ template: 'views/modal/projectCreate.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 400,
+ showClose: true,
+ closeByDocument: false
+ })
+ }
+
+ function createName(name) {
+
+ mainFactory.createProjectName().post({
+ 'action': 'create_project',
+ 'args': {
+ 'name': name,
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create project success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getProjectList();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'failed',
+ body: 'create project failed',
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'failed',
+ body: 'Something Wrong',
+ timeout: 3000
+ });
+ })
+ }
+
+ function gotoDetail(id) {
+ $state.go('app2.projectdetail', { projectId: id })
+ }
+
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteProject = function deleteProject() {
+ mainFactory.deleteProject().delete({ 'project_id': $scope.deleteId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete Project success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getProjectList();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/projectDetail.controller.js b/gui/app/scripts/controllers/projectDetail.controller.js
new file mode 100644
index 000000000..4ab4a055a
--- /dev/null
+++ b/gui/app/scripts/controllers/projectDetail.controller.js
@@ -0,0 +1,690 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('ProjectDetailController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog', '$localStorage', '$loading', '$interval',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog, $localStorage, $loading, $interval) {
+
+
+ init();
+ // $scope.taskListDisplay = [];
+ $scope.blisterPackTemplates = [{ id: 1, name: "Test Case" }, { id: 2, name: "Test Suite" }]
+ $scope.selectType = null;
+ $scope.ifHasEnv = false;
+ $scope.ifHasCase = false;
+ $scope.ifHasSuite = false;
+ $scope.$on('$destroy', function() {
+ $interval.cancel($scope.intervalCount)
+ });
+ $scope.finalTaskListDisplay = [];
+
+
+ function init() {
+
+
+ getProjectDetail();
+
+ $scope.openCreate = openCreate;
+ $scope.createTask = createTask;
+ $scope.constructTestSuit = constructTestSuit;
+ $scope.addEnvToTask = addEnvToTask;
+ $scope.triggerContent = triggerContent;
+ $scope.constructTestCase = constructTestCase;
+ $scope.getTestDeatil = getTestDeatil;
+ $scope.confirmAddCaseOrSuite = confirmAddCaseOrSuite;
+ $scope.runAtask = runAtask;
+ $scope.gotoDetail = gotoDetail;
+ $scope.gotoReport = gotoReport;
+ $scope.gotoModify = gotoModify;
+ $scope.goBack = goBack;
+ $scope.goToExternal = goToExternal;
+
+
+ }
+
+ function getProjectDetail() {
+ if ($scope.intervalCount != undefined) {
+ $interval.cancel($scope.intervalCount);
+ }
+ $loading.start('key');
+ $scope.taskListDisplay = [];
+ $scope.finalTaskListDisplay = [];
+ mainFactory.getProjectDetail().get({
+ project_id: $stateParams.projectId
+ }).$promise.then(function(response) {
+ $loading.finish('key');
+ if (response.status == 1) {
+
+ $scope.projectData = response.result.project;
+ if ($scope.projectData.tasks.length != 0) {
+
+
+ for (var i = 0; i < $scope.projectData.tasks.length; i++) {
+ getDetailTaskForList($scope.projectData.tasks[i]);
+ }
+ $scope.intervalCount = $interval(function() {
+ getDetailForEachTask();
+ }, 10000);
+ } else {
+
+ if ($scope.intervalCount != undefined) {
+ $interval.cancel($scope.intervalCount);
+ }
+ }
+ } else {
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ // function getProjectDetailSimple() {
+ // getDetailForEachTask();
+ // }
+
+ function openCreate() {
+ $scope.newUUID = null;
+ $scope.displayEnvName = null;
+ $scope.selectEnv = null;
+ $scope.selectCase = null;
+ $scope.selectType = null;
+ $scope.contentInfo = null;
+ $scope.ifHasEnv = false;
+ $scope.ifHasCase = false;
+ $scope.ifHasSuite = false;
+
+ // getEnvironmentList();
+ $scope.selectEnv = null;
+ ngDialog.open({
+ template: 'views/modal/taskCreate.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 800,
+ showClose: true,
+ closeByDocument: false,
+ preCloseCallback: function(value) {
+ getProjectDetail();
+ },
+ })
+ }
+
+ function createTask(name) {
+ mainFactory.createTask().post({
+ 'action': 'create_task',
+ 'args': {
+ 'name': name,
+ 'project_id': $stateParams.projectId
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create task success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.newUUID = response.result.uuid;
+ getEnvironmentList();
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ }
+
+
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getDetailTaskForList(id) {
+
+ mainFactory.getTaskDetail().get({
+ 'taskId': id
+ }).$promise.then(function(response) {
+
+ if (response.status == 1) {
+ if (response.result.task.status == -1) {
+ response.result.task['stausWidth'] = '5%';
+ } else if (response.result.task.status == 0) {
+ response.result.task['stausWidth'] = '50%';
+ } else if (response.result.task.status == 1) {
+ response.result.task['stausWidth'] = '100%';
+ } else if (response.result.task.status == 2) {
+ response.result.task['stausWidth'] = 'red';
+ }
+ $scope.taskListDisplay.push(response.result.task);
+ console.log($scope.taskListDisplay);
+
+ $scope.finalTaskListDisplay = $scope.taskListDisplay;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function getDetailTaskForListSimple(id, index) {
+
+ mainFactory.getTaskDetail().get({
+ 'taskId': id
+ }).$promise.then(function(response) {
+
+ if (response.status == 1) {
+ if (response.result.task.status == -1) {
+
+ $scope.finalTaskListDisplay[index].stausWidth = '5%';
+ $scope.finalTaskListDisplay[index].status = response.result.task.status;
+ } else if (response.result.task.status == 0) {
+
+ $scope.finalTaskListDisplay[index].stausWidth = '50%';
+ $scope.finalTaskListDisplay[index].status = response.result.task.status;
+ } else if (response.result.task.status == 1) {
+
+ $scope.finalTaskListDisplay[index].stausWidth = '100%';
+ $scope.finalTaskListDisplay[index].status = response.result.task.status;
+ } else if (response.result.task.status == 2) {
+
+ $scope.finalTaskListDisplay[index].stausWidth = 'red';
+ $scope.finalTaskListDisplay[index].status = response.result.task.status;
+ }
+
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function getDetailForEachTask() {
+ for (var i = 0; i < $scope.finalTaskListDisplay.length; i++) {
+ if ($scope.finalTaskListDisplay[i].status != 1 && $scope.finalTaskListDisplay[i].status != -1) {
+ getDetailTaskForListSimple($scope.finalTaskListDisplay[i].uuid, i);
+ }
+ }
+ }
+
+ function getEnvironmentList() {
+ mainFactory.getEnvironmentList().get().$promise.then(function(response) {
+ $scope.environmentList = response.result.environments;
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function constructTestSuit(id, name) {
+ $scope.displayEnvName = name;
+ $scope.selectEnv = id;
+
+ }
+
+ function constructTestCase(name) {
+
+ $scope.selectCase = name;
+ if ($scope.selectType.name == 'Test Case') {
+ getCaseInfo();
+ } else {
+ getSuiteInfo();
+ }
+
+ }
+
+
+
+
+ function addEnvToTask() {
+ mainFactory.taskAddEnv().put({
+ 'taskId': $scope.newUUID,
+ 'action': 'add_environment',
+ 'args': {
+ 'task_id': $scope.newUUID,
+ 'environment_id': $scope.selectEnv
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'add environment success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.ifHasEnv = true;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ }
+
+
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ })
+ }
+
+ function triggerContent(name) {
+ $scope.selectCase = null;
+ $scope.displayTable = true;
+
+ $scope.selectType = name;
+ if (name.name == 'Test Case') {
+ getTestcaseList();
+ } else if (name.name == 'Test Suite') {
+ getsuiteList();
+ }
+ }
+
+ function getTestcaseList() {
+ mainFactory.getTestcaselist().get({
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.testcaselist = response.result;
+
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getsuiteList() {
+ mainFactory.suiteList().get({
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.testsuitlist = response.result.testsuites;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getTestDeatil() {
+
+
+ if ($scope.selectType.name == 'Test Case') {
+ getTestcaseDetail();
+ } else {
+ getSuiteDetail();
+ }
+
+ }
+
+ function getCaseInfo() {
+
+
+
+ mainFactory.getTestcaseDetail().get({
+ 'testcasename': $scope.selectCase
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+
+ $scope.contentInfo = response.result.testcase;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getSuiteInfo() {
+ mainFactory.suiteDetail().get({
+ 'suiteName': $scope.selectCase.split('.')[0]
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.contentInfo = response.result.testsuite;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function getSuiteDetail() {
+ mainFactory.suiteDetail().get({
+ 'suiteName': $scope.selectCase.split('.')[0]
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.displayTable = false;
+ $scope.contentInfo = response.result.testsuite;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function getTestcaseDetail() {
+ mainFactory.getTestcaseDetail().get({
+ 'testcasename': $scope.selectCase
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+
+ $scope.displayTable = false;
+ $scope.contentInfo = response.result.testcase;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function addCasetoTask(content) {
+ mainFactory.taskAddEnv().put({
+ 'taskId': $scope.newUUID,
+ 'action': 'add_case',
+ 'args': {
+ 'task_id': $scope.newUUID,
+ 'case_name': $scope.selectCase,
+ 'case_content': content
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'add test case success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.ifHasCase = true;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ })
+ }
+
+ function addSuitetoTask(content) {
+ mainFactory.taskAddEnv().put({
+ 'taskId': $scope.newUUID,
+ 'action': 'add_suite',
+ 'args': {
+ 'task_id': $scope.newUUID,
+ 'suite_name': $scope.selectCase.split('.')[0],
+ 'suite_content': content
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'add test suite success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.ifHasSuite = true;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'wrong',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'something wrong',
+ timeout: 3000
+ });
+ })
+ }
+
+ function confirmAddCaseOrSuite(content) {
+ if ($scope.selectType.name == "Test Case") {
+ addCasetoTask(content);
+ } else {
+ addSuitetoTask(content);
+ }
+ }
+
+ function runAtask(id) {
+ mainFactory.taskAddEnv().put({
+ 'taskId': id,
+ 'action': 'run',
+ 'args': {
+ 'task_id': id
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'run a task success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ // getProjectDetail();
+ } else {
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ $scope.runAtaskForTable = function runAtaskForTable(id) {
+ mainFactory.taskAddEnv().put({
+ 'taskId': id,
+ 'action': 'run',
+ 'args': {
+ 'task_id': id
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ // toaster.pop({
+ // type: 'success',
+ // title: 'run a task success',
+ // body: 'you can go next step',
+ // timeout: 3000
+ // });
+ // ngDialog.close();
+ getProjectDetail();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.result,
+ timeout: 3000
+ });
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ function gotoDetail(id) {
+
+
+ $state.go('app2.tasklist', { taskId: id });
+
+ }
+
+ function gotoReport(id) {
+ $state.go('app2.report', { taskId: id });
+ }
+
+ function gotoModify(id) {
+ $state.go('app2.taskModify', { taskId: id });
+ }
+
+ function goBack() {
+ window.history.back();
+ }
+
+ function goToExternal() {
+ window.open(External_URL, '_blank');
+ }
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteTask = function deleteTask() {
+ mainFactory.deleteTask().delete({ 'task_id': $scope.deleteId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete Task success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getProjectDetail();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/report.controller.js b/gui/app/scripts/controllers/report.controller.js
new file mode 100644
index 000000000..9b6b5958b
--- /dev/null
+++ b/gui/app/scripts/controllers/report.controller.js
@@ -0,0 +1,115 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('ReportController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog) {
+
+
+ init();
+
+
+ function init() {
+ getDetailTaskForList();
+
+
+
+ }
+ $scope.goBack = function goBack() {
+ window.history.back();
+ }
+
+ function getDetailTaskForList(id) {
+ mainFactory.getTaskDetail().get({
+ 'taskId': $stateParams.taskId
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ if (response.result.task.status == -1) {
+ response.result.task['stausWidth'] = '5%';
+ } else if (response.result.task.status == 0) {
+ response.result.task['stausWidth'] = '50%';
+ } else if (response.result.task.status == 1) {
+ response.result.task['stausWidth'] = '100%';
+ } else if (response.result.task.status == 2) {
+ response.result.task['stausWidth'] = 'red';
+ }
+ $scope.result = response.result.task;
+ $scope.testcaseinfo = response.result.task.result.testcases;
+ var key = Object.keys($scope.testcaseinfo);
+ $scope.testcaseResult = $scope.testcaseinfo[key];
+
+ $scope.envIdForTask = response.result.task.environment_id;
+ getItemIdDetail();
+
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+ $scope.goToExternal = function goToExternal(id) {
+ var url = External_URL + ':' + $scope.jumpPort + '/dashboard/db' + '/' + id;
+
+ window.open(url, '_blank');
+ }
+
+ function getItemIdDetail() {
+ $scope.displayContainerInfo = [];
+ mainFactory.ItemDetail().get({
+ 'envId': $scope.envIdForTask
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ if (response.result.environment.container_id.grafana != null) {
+ getConDetail(response.result.environment.container_id.grafana);
+
+ } else {
+ $scope.jumpPort = 3000;
+ }
+
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getConDetail(id) {
+ mainFactory.containerDetail().get({
+ 'containerId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ // $scope.podData = response.result;
+ $scope.jumpPort = response.result.container.port;
+
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+
+ }
+
+
+
+
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/suitecreate.controller.js b/gui/app/scripts/controllers/suitecreate.controller.js
new file mode 100644
index 000000000..4a7b6fe85
--- /dev/null
+++ b/gui/app/scripts/controllers/suitecreate.controller.js
@@ -0,0 +1,104 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('suitcreateController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog) {
+
+
+ init();
+
+
+ function init() {
+
+ getTestcaseList();
+ $scope.constructTestSuit = constructTestSuit;
+ $scope.openDialog = openDialog;
+ $scope.createSuite = createSuite;
+
+ }
+
+ function getTestcaseList() {
+ mainFactory.getTestcaselist().get({
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.testcaselist = response.result;
+
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ $scope.testsuiteList = [];
+ $scope.suitReconstructList = [];
+
+ function constructTestSuit(name) {
+
+ var index = $scope.testsuiteList.indexOf(name);
+ if (index > -1) {
+ $scope.testsuiteList.splice(index, 1);
+ } else {
+ $scope.testsuiteList.push(name);
+ }
+
+
+ $scope.suitReconstructList = $scope.testsuiteList;
+
+ }
+
+ function createSuite(name) {
+ mainFactory.suiteCreate().post({
+ 'action': 'create_suite',
+ 'args': {
+ 'name': name,
+ 'testcases': $scope.testsuiteList
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'create suite success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ } else {
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function openDialog() {
+ ngDialog.open({
+ template: 'views/modal/suiteName.html',
+ className: 'ngdialog-theme-default',
+ scope: $scope,
+ width: 314,
+ showClose: true,
+ closeByDocument: false
+ })
+ }
+
+
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/suitedetail.controller.js b/gui/app/scripts/controllers/suitedetail.controller.js
new file mode 100644
index 000000000..0dd39c389
--- /dev/null
+++ b/gui/app/scripts/controllers/suitedetail.controller.js
@@ -0,0 +1,48 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('suiteDetailController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster) {
+
+
+ init();
+
+
+ function init() {
+
+ getSuiteDetail();
+
+ }
+
+ function getSuiteDetail() {
+ mainFactory.suiteDetail().get({
+ 'suiteName': $stateParams.name
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.suiteinfo = response.result.testsuite;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+ $scope.goBack = function goBack() {
+ window.history.back();
+ }
+
+
+
+
+
+
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/task.controller.js b/gui/app/scripts/controllers/task.controller.js
new file mode 100644
index 000000000..05546f9bf
--- /dev/null
+++ b/gui/app/scripts/controllers/task.controller.js
@@ -0,0 +1,175 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('TaskController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog) {
+
+
+ init();
+
+
+ function init() {
+ getDetailTaskForList();
+
+ }
+
+ function getDetailTaskForList() {
+ mainFactory.getTaskDetail().get({
+ 'taskId': $stateParams.taskId
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ if (response.result.task.status == -1) {
+ response.result.task['stausWidth'] = '5%';
+ } else if (response.result.task.status == 0) {
+ response.result.task['stausWidth'] = '50%';
+ } else if (response.result.task.status == 1) {
+ response.result.task['stausWidth'] = '100%';
+ } else if (response.result.task.status == 2) {
+ response.result.task['stausWidth'] = 'red';
+ }
+
+ $scope.taskDetailData = response.result.task;
+ if ($scope.taskDetailData.environment_id != null) {
+ getItemIdDetail($scope.taskDetailData.environment_id);
+ }
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function getItemIdDetail(id) {
+ mainFactory.ItemDetail().get({
+ 'envId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.displayEnv = response.result.environment;
+
+ if (response.result.environment.pod_id != null) {
+ getPodDetail(response.result.environment.pod_id);
+ } else if (response.result.environment.image_id != null) {
+ getImageDetail(response.result.environment.image_id);
+ } else if (response.result.environment.openrc_id != null) {
+ getOpenrcDetail(response.result.environment.openrc_id != null);
+ } else if (response.result.environment.container_id.length != 0) {
+ $scope.displayContainerDetail = [];
+ var containerArray = response.result.environment.container_id;
+ for (var i = 0; i < containerArray.length; i++) {
+ getContainerId(containerArray[i]);
+ }
+
+ }
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //getopenRcid
+ function getOpenrcDetail(openrcId) {
+ mainFactory.getEnvironmentDetail().get({
+ 'openrc_id': openrcId
+ }).$promise.then(function(response) {
+ //openrc数据
+ $scope.openrcInfo = response.result;
+ // buildToEnvInfo($scope.openrcInfo.openrc)
+ }, function(response) {
+
+ })
+ }
+
+
+ //getImgDetail
+ function getImageDetail(id) {
+ mainFactory.ImageDetail().get({
+ 'image_id': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageDetail = response.result.image;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //getPodDetail
+ function getPodDetail(id) {
+ mainFactory.podDeatil().get({
+ 'podId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.podDetail = response.result.pod;
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+ //getContainerDetail
+ function getContainerId(containerId) {
+ mainFactory.containerDetail().get({
+ 'containerId': containerId
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.container = response.result.container;
+ $scope.displayContainerDetail.push($scope.container);
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+ $scope.goBack = function goBack() {
+ window.history.back();
+ }
+
+
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/taskModify.controller.js b/gui/app/scripts/controllers/taskModify.controller.js
new file mode 100644
index 000000000..757d65866
--- /dev/null
+++ b/gui/app/scripts/controllers/taskModify.controller.js
@@ -0,0 +1,533 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('TaskModifyController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster) {
+
+
+ init();
+ $scope.blisterPackTemplates = [{ id: 1, name: "Test Case" }, { id: 2, name: "Test Suite" }]
+ $scope.selectType = null;
+
+ $scope.sourceShow = null;
+
+
+
+ function init() {
+ getDetailTaskForList();
+ getEnvironmentList();
+ $scope.triggerContent = triggerContent;
+ $scope.constructTestSuit = constructTestSuit;
+ $scope.constructTestCase = constructTestCase;
+ $scope.getTestDeatil = getTestDeatil;
+ $scope.confirmToServer = confirmToServer;
+ $scope.addEnvToTask = addEnvToTask;
+ }
+
+ function getDetailTaskForList() {
+ mainFactory.getTaskDetail().get({
+ 'taskId': $stateParams.taskId
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ if (response.result.task.status == -1) {
+ response.result.task['stausWidth'] = '5%';
+ } else if (response.result.task.status == 0) {
+ response.result.task['stausWidth'] = '50%';
+ } else if (response.result.task.status == 1) {
+ response.result.task['stausWidth'] = '100%';
+ } else if (response.result.task.status == 2) {
+ response.result.task['stausWidth'] = 'red';
+ }
+
+ $scope.taskDetailData = response.result.task;
+ $scope.selectEnv = $scope.taskDetailData.environment_id;
+
+ if ($scope.taskDetailData.environment_id != null) {
+ getItemIdDetail($scope.taskDetailData.environment_id);
+ }
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getItemIdDetail(id) {
+ mainFactory.ItemDetail().get({
+ 'envId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.envName = response.result.environment.name;
+ // $scope.selectEnv = $scope.envName;
+ } else {
+ alert('Something Wrong!');
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //getopenRcid
+ function getOpenrcDetail(openrcId) {
+ mainFactory.getEnvironmentDetail().get({
+ 'openrc_id': openrcId
+ }).$promise.then(function(response) {
+ $scope.openrcInfo = response.result;
+ // buildToEnvInfo($scope.openrcInfo.openrc)
+ }, function(response) {
+
+ })
+ }
+
+
+ //getImgDetail
+ function getImageDetail(id) {
+ mainFactory.ImageDetail().get({
+ 'image_id': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.imageDetail = response.result.image;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ //getPodDetail
+ function getPodDetail(id) {
+ mainFactory.podDeatil().get({
+ 'podId': id
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.podDetail = response.result.pod;
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+ //getContainerDetail
+ function getContainerId(containerId) {
+ mainFactory.containerDetail().get({
+ 'containerId': containerId
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.container = response.result.container;
+ $scope.displayContainerDetail.push($scope.container);
+
+ } else {
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getEnvironmentList() {
+ mainFactory.getEnvironmentList().get().$promise.then(function(response) {
+ $scope.environmentList = response.result.environments;
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function triggerContent(name) {
+ $scope.selectCase = null;
+ $scope.displayTable = true;
+
+ $scope.selectType = name;
+ if (name.name == 'Test Case') {
+ $scope.taskDetailData.suite = false;
+ getTestcaseList();
+ } else if (name.name == 'Test Suite') {
+ $scope.taskDetailData.suite = true;
+ getsuiteList();
+ }
+ }
+
+ function getTestcaseList() {
+ mainFactory.getTestcaselist().get({
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.testcaselist = response.result;
+
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getsuiteList() {
+ mainFactory.suiteList().get({
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.testsuitlist = response.result.testsuites;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function constructTestSuit(id, name) {
+
+ $scope.envName = name;
+ $scope.selectEnv = id;
+
+ }
+
+ function constructTestCase(name) {
+
+ $scope.selectCase = name;
+ if ($scope.selectType.name == 'Test Case') {
+ getCaseInfo();
+ } else {
+ getSuiteInfo();
+ }
+
+ }
+
+ function getCaseInfo() {
+
+
+
+ mainFactory.getTestcaseDetail().get({
+ 'testcasename': $scope.selectCase
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+
+ $scope.contentInfo = response.result.testcase;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function getSuiteInfo() {
+ mainFactory.suiteDetail().get({
+ 'suiteName': $scope.selectCase.split('.')[0]
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.contentInfo = response.result.testsuite;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function getTestDeatil() {
+
+
+ if ($scope.selectType.name == 'Test Case') {
+ getTestcaseDetail();
+ } else {
+ getSuiteDetail();
+ }
+
+ }
+
+ function getSuiteDetail() {
+ mainFactory.suiteDetail().get({
+ 'suiteName': $scope.selectCase.split('.')[0]
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.displayTable = false;
+ $scope.contentInfo = response.result.testsuite;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+ function getTestcaseDetail() {
+ mainFactory.getTestcaseDetail().get({
+ 'testcasename': $scope.selectCase
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+
+ $scope.displayTable = false;
+ $scope.contentInfo = response.result.testcase;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+ function addCasetoTask(content) {
+ mainFactory.taskAddEnv().put({
+ 'taskId': $stateParams.taskId,
+ 'action': 'add_case',
+ 'args': {
+ 'task_id': $stateParams.taskId,
+ 'case_name': $scope.selectCase,
+ 'case_content': content
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'add test case success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.ifHasCase = true;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: '',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: '',
+ timeout: 3000
+ });
+ })
+ }
+
+ function addSuitetoTask(content) {
+ mainFactory.taskAddEnv().put({
+ 'taskId': $stateParams.taskId,
+ 'action': 'add_suite',
+ 'args': {
+ 'task_id': $stateParams.taskId,
+ 'suite_name': $scope.selectCase.split('.')[0],
+ 'suite_content': content
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'add test suite success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.ifHasSuite = true;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'wrong',
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'something wrong',
+ timeout: 3000
+ });
+ })
+ }
+ $scope.changeStatussourceTrue = function changeStatussourceTrue() {
+ $scope.selectCase = null;
+ $scope.sourceShow = true;
+ }
+
+ $scope.changeStatussourceFalse = function changeStatussourceFalse() {
+ $scope.sourceShow = false;
+ }
+
+ function confirmToServer(content1, content2) {
+
+ var content;
+ if ($scope.sourceShow == false) {
+ content = content2;
+ $scope.selectCase = $scope.taskDetailData.case_name;
+ } else if ($scope.sourceShow == true) {
+ content = content1;
+ }
+ if ($scope.selectCase == 'Test Case' || $scope.taskDetailData.suite == false) {
+
+ addCasetoTask(content);
+ } else {
+ addSuitetoTask(content);
+ }
+ }
+
+
+ function addEnvToTask() {
+
+ mainFactory.taskAddEnv().put({
+ 'taskId': $stateParams.taskId,
+ 'action': 'add_environment',
+ 'args': {
+ 'task_id': $stateParams.taskId,
+ 'environment_id': $scope.selectEnv
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'add environment success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ $scope.ifHasEnv = true;
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ }
+
+
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'create task wrong',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ })
+ }
+
+ $scope.goBack = function goBack() {
+ window.history.back();
+ }
+
+ $scope.runAtask = function runAtask() {
+ mainFactory.taskAddEnv().put({
+ 'taskId': $stateParams.taskId,
+ 'action': 'run',
+ 'args': {
+ 'task_id': $stateParams.taskId
+ }
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'run a task success',
+ body: 'go to task list page...',
+ timeout: 3000
+ });
+ setTimeout(function() {
+ window.history.back();
+ }, 2000);
+
+
+
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: response.error_msg,
+ timeout: 3000
+ });
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ ]);
diff --git a/gui/app/scripts/controllers/testcase.controller.js b/gui/app/scripts/controllers/testcase.controller.js
new file mode 100644
index 000000000..616ceb4a8
--- /dev/null
+++ b/gui/app/scripts/controllers/testcase.controller.js
@@ -0,0 +1,154 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('TestcaseController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog', '$loading',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog, $loading) {
+
+
+ init();
+ $scope.loadingOPENrc = false;
+
+
+ function init() {
+ $scope.testcaselist = [];
+ getTestcaseList();
+ $scope.gotoDetail = gotoDetail;
+ $scope.uploadFiles = uploadFiles;
+
+
+ }
+
+ function getTestcaseList() {
+ $loading.start('key');
+ mainFactory.getTestcaselist().get({
+
+ }).$promise.then(function(response) {
+ $loading.finish('key');
+ if (response.status == 1) {
+ $scope.testcaselist = response.result;
+
+
+ }
+ }, function(error) {
+ $loading.finish('key');
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function gotoDetail(name) {
+ $state.go('app2.testcasedetail', { name: name });
+ }
+
+
+ function uploadFiles($file, $invalidFiles) {
+ $scope.loadingOPENrc = true;
+
+ $scope.displayOpenrcFile = $file;
+ timeConstruct($scope.displayOpenrcFile.lastModified);
+ Upload.upload({
+ url: Base_URL + '/api/v2/yardstick/testcases',
+ data: { file: $file, 'action': 'upload_case' }
+ }).then(function(response) {
+
+ $scope.loadingOPENrc = false;
+ if (response.data.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'upload success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+
+
+
+ } else {
+
+ }
+
+ }, function(error) {
+ $scope.uploadfile = null;
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function timeConstruct(array) {
+ var date = new Date(1398250549490);
+ var Y = date.getFullYear() + '-';
+ var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
+ var D = date.getDate() + ' ';
+ var h = date.getHours() + ':';
+ var m = date.getMinutes() + ':';
+ var s = date.getSeconds();
+ $scope.filelastModified = Y + M + D + h + m + s;
+
+ }
+ $scope.goBack = function goBack() {
+ $state.go('app2.projectList');
+ }
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id;
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteTestCase = function deleteTestCase() {
+ mainFactory.deleteTestCase().delete({ 'caseName': $scope.deleteId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete Test Case success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getTestcaseList();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+
+ })
+ }
+
+
+
+
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/testcasedetail.controller.js b/gui/app/scripts/controllers/testcasedetail.controller.js
new file mode 100644
index 000000000..4e824ca85
--- /dev/null
+++ b/gui/app/scripts/controllers/testcasedetail.controller.js
@@ -0,0 +1,50 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('testcaseDetailController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster) {
+
+
+ init();
+
+
+ function init() {
+
+ getTestcaseDetail();
+
+
+ }
+
+ function getTestcaseDetail() {
+ mainFactory.getTestcaseDetail().get({
+ 'testcasename': $stateParams.name
+
+ }).$promise.then(function(response) {
+ if (response.status == 1) {
+ $scope.testcaseInfo = response.result.testcase;
+
+ }
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ $scope.goBack = function goBack() {
+ window.history.back();
+ }
+
+
+
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/controllers/testsuit.controller.js b/gui/app/scripts/controllers/testsuit.controller.js
new file mode 100644
index 000000000..abc9095c7
--- /dev/null
+++ b/gui/app/scripts/controllers/testsuit.controller.js
@@ -0,0 +1,119 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .controller('SuiteListController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', 'ngDialog', '$loading',
+ function($scope, $state, $stateParams, mainFactory, Upload, toaster, ngDialog, $loading) {
+
+
+ init();
+
+
+ function init() {
+ $scope.testsuitlist = [];
+ getsuiteList();
+ $scope.gotoDetail = gotoDetail;
+ $scope.gotoCreateSuite = gotoCreateSuite;
+
+
+ }
+
+ function getsuiteList() {
+ $loading.start('key');
+ mainFactory.suiteList().get({
+
+ }).$promise.then(function(response) {
+ $loading.finish('key');
+ if (response.status == 1) {
+ $scope.testsuitlist = response.result.testsuites;
+
+ }
+ }, function(error) {
+ $loading.finish('key');
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+ function gotoDetail(name) {
+ var temp = name.split('.')[0];
+
+ $state.go('app2.suitedetail', { name: temp })
+
+ }
+
+ function gotoCreateSuite() {
+ $state.go('app2.suitcreate');
+ }
+
+ $scope.goBack = function goBack() {
+ $state.go('app2.projectList');
+ }
+
+
+ $scope.openDeleteEnv = function openDeleteEnv(id, name) {
+ $scope.deleteName = name;
+ $scope.deleteId = id.split('.')[0];
+ ngDialog.open({
+ template: 'views/modal/deleteConfirm.html',
+ scope: $scope,
+ className: 'ngdialog-theme-default',
+ width: 500,
+ showClose: true,
+ closeByDocument: false
+ })
+
+ }
+
+ $scope.deleteSuite = function deleteSuite() {
+ mainFactory.deleteTestSuite().delete({ 'suite_name': $scope.deleteId }).$promise.then(function(response) {
+ if (response.status == 1) {
+ toaster.pop({
+ type: 'success',
+ title: 'delete Test Suite success',
+ body: 'you can go next step',
+ timeout: 3000
+ });
+ ngDialog.close();
+ getTestcaseList();
+ } else {
+ toaster.pop({
+ type: 'error',
+ title: 'Wrong',
+ body: response.result,
+ timeout: 3000
+ });
+ }
+
+ }, function(error) {
+ toaster.pop({
+ type: 'error',
+ title: 'fail',
+ body: 'unknow error',
+ timeout: 3000
+ });
+ })
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ ]); \ No newline at end of file
diff --git a/gui/app/scripts/factory/main.factory.js b/gui/app/scripts/factory/main.factory.js
new file mode 100644
index 000000000..f8e9df9a1
--- /dev/null
+++ b/gui/app/scripts/factory/main.factory.js
@@ -0,0 +1,247 @@
+'use strict';
+
+/**
+ * get data factory
+ */
+
+
+var Base_URL;
+var Grafana_URL;
+
+angular.module('yardStickGui2App')
+ .factory('mainFactory', ['$resource','$rootScope','$http', '$location',function($resource, $rootScope,$http,$location) {
+
+ Base_URL = 'http://' + $location.host() + ':' + $location.port();
+ Grafana_URL = 'http://' + $location.host();
+
+ return {
+
+ postEnvironmentVariable: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/openrcs', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ uploadOpenrc: function() {
+ return $resource(Base_URL + '/ap/v2/yardstick/openrcs', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ getEnvironmentList: function() {
+ return $resource(Base_URL+ '/api/v2/yardstick/environments', {}, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ getEnvironmentDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/openrcs/:openrc_id', { openrc_id: "@openrc_id" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ addEnvName: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/environments', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ ItemDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/environments/:envId', { envId: "@envId" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ ImageDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/images/:image_id', { image_id: "@image_id" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ podDeatil: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/pods/:podId', { podId: "@podId" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ containerDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/containers/:containerId', { containerId: "@containerId" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ ImageList: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/images', {}, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ uploadImage: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/images', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ getPodDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/pods/:podId', { podId: "@podId" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ runAcontainer: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/containers', { podId: "@podId" }, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ getTestcaselist: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testcases', {}, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ getTestcaseDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testcases/:testcasename', { testcasename: "@testcasename" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ suiteList: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testsuites', {}, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ suiteDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testsuites/:suiteName', { suiteName: "@suiteName" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ suiteCreate: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testsuites', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ projectList: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/projects', {}, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+ createProjectName: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/projects', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ getProjectDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/projects/:project_id', { project_id: "@project_id" }, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ createTask: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/tasks', {}, {
+ 'post': {
+ method: 'POST'
+ }
+ })
+ },
+ getTaskDetail: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/tasks/:taskId', { taskId: "@taskId" }, {
+ 'get': {
+ method: 'GET'
+ }
+ })
+ },
+
+ taskAddEnv: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/tasks/:taskId', { taskId: "@taskId" }, {
+ 'put': {
+ method: 'PUT'
+ }
+ })
+ },
+ //delete operate
+ deleteEnv: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/environments/:env_id', { env_id: '@env_id' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deleteOpenrc: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/openrcs/:openrc', { openrc: '@openrc' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deletePod: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/pods/:podId', { podId: '@podId' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deleteContainer: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/containers/:containerId', { containerId: '@containerId' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deleteTestCase: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testcases/:caseName', { caseName: '@caseName' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deleteTestSuite: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/testsuites/:suite_name', { suite_name: '@suite_name' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deleteProject: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/projects/:project_id', { project_id: '@project_id' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ },
+ deleteTask: function() {
+ return $resource(Base_URL + '/api/v2/yardstick/tasks/:task_id', { task_id: '@task_id' }, {
+ 'delete': {
+ method: 'DELETE'
+ }
+ })
+ }
+
+ };
+ }]);
diff --git a/gui/app/scripts/router.config.js b/gui/app/scripts/router.config.js
new file mode 100644
index 000000000..b42954272
--- /dev/null
+++ b/gui/app/scripts/router.config.js
@@ -0,0 +1,184 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+ .run(
+ ['$rootScope', '$state', '$stateParams',
+ function($rootScope, $state, $stateParams) {
+ $rootScope.$state = $state;
+ $rootScope.$stateParams = $stateParams;
+
+ }
+ ]
+ )
+ .config(['$stateProvider', '$urlRouterProvider', '$locationProvider',
+ function($stateProvider, $urlRouterProvider, $locationProvider) {
+ $urlRouterProvider
+ .otherwise('main/environment');
+
+
+
+
+ $stateProvider
+
+ .state('app2', {
+ url: "/main",
+ controller: 'ContentController',
+ templateUrl: "views/main2.html",
+ ncyBreadcrumb: {
+ label: 'Main'
+ }
+ })
+ .state('app', {
+ url: "/main",
+ controller: 'ContentController',
+ templateUrl: "views/main.html",
+ ncyBreadcrumb: {
+ label: 'Main'
+ }
+ })
+
+ .state('app2.environment', {
+ url: '/environment',
+ templateUrl: 'views/environmentList.html',
+ controller: 'MainCtrl',
+ ncyBreadcrumb: {
+ label: 'Environment'
+ }
+ })
+ .state('app2.testcase', {
+ url: '/testcase',
+ templateUrl: 'views/testcaselist.html',
+ controller: 'TestcaseController',
+ ncyBreadcrumb: {
+ label: 'Test Case'
+ }
+ })
+ .state('app2.testsuite', {
+ url: '/suite',
+ templateUrl: 'views/suite.html',
+ controller: 'SuiteListController',
+ ncyBreadcrumb: {
+ label: 'Test Suite'
+ }
+ })
+ .state('app2.suitcreate', {
+ url: '/suitcreate',
+ templateUrl: 'views/testcasechoose.html',
+ controller: 'suitcreateController',
+ ncyBreadcrumb: {
+ label: 'Suite Create'
+ }
+ })
+ .state('app2.testcasedetail', {
+ url: '/testdetail/:name',
+ templateUrl: 'views/testcasedetail.html',
+ controller: 'testcaseDetailController',
+ ncyBreadcrumb: {
+ label: 'Test Case Detail'
+ },
+ params: { name: null }
+ })
+ .state('app2.suitedetail', {
+ url: '/suitedetail/:name',
+ templateUrl: 'views/suitedetail.html',
+ controller: 'suiteDetailController',
+ ncyBreadcrumb: {
+ label: 'Suite Detail'
+ },
+ params: { name: null }
+ })
+ .state('app.environmentDetail', {
+ url: '/envDetail/:uuid',
+ templateUrl: 'views/environmentDetail.html',
+ controller: 'DetailController',
+ params: { uuid: null, ifNew: null },
+ ncyBreadcrumb: {
+ label: 'Environment Detail'
+ }
+ })
+ .state('app.uploadImage', {
+ url: '/envimageDetail/:uuid',
+ templateUrl: 'views/uploadImage.html',
+ controller: 'ImageController',
+ params: { uuid: null },
+ ncyBreadcrumb: {
+ label: 'Upload Image'
+ }
+
+ })
+ .state('app.podUpload', {
+ url: '/envpodupload/:uuid',
+ templateUrl: 'views/podupload.html',
+ controller: 'PodController',
+ params: { uuid: null },
+ ncyBreadcrumb: {
+ label: 'Pod Upload'
+ }
+ })
+ .state('app.container', {
+ url: '/envcontainer/:uuid',
+ templateUrl: 'views/container.html',
+ controller: 'ContainerController',
+ params: { uuid: null },
+ ncyBreadcrumb: {
+ label: 'Container Manage'
+ }
+ })
+ .state('app2.projectList', {
+ url: '/project',
+ templateUrl: 'views/projectList.html',
+ controller: 'ProjectController',
+ ncyBreadcrumb: {
+ label: 'Project'
+ }
+
+ })
+ .state('app2.tasklist', {
+ url: '/task/:taskId',
+ templateUrl: 'views/taskList.html',
+ controller: 'TaskController',
+ params: { taskId: null },
+ ncyBreadcrumb: {
+ label: 'Task'
+ }
+
+ })
+ .state('app2.report', {
+ url: '/report/:taskId',
+ templateUrl: 'views/report.html',
+ controller: 'ReportController',
+ params: { taskId: null },
+ ncyBreadcrumb: {
+ label: 'Report'
+ }
+
+ })
+ .state('app2.projectdetail', {
+ url: '/projectdetail/:projectId',
+ templateUrl: 'views/projectdetail.html',
+ controller: 'ProjectDetailController',
+ params: { projectId: null },
+ ncyBreadcrumb: {
+ label: 'Project Detail'
+ }
+
+ })
+ .state('app2.taskModify', {
+ url: '/taskModify/:taskId',
+ templateUrl: 'views/taskmodify.html',
+ controller: 'TaskModifyController',
+ params: { taskId: null },
+ ncyBreadcrumb: {
+ label: 'Modify Task'
+ }
+
+
+ })
+
+
+
+
+
+ }
+ ])
+ .run();
diff --git a/gui/app/styles/main.css b/gui/app/styles/main.css
new file mode 100644
index 000000000..e13a66bce
--- /dev/null
+++ b/gui/app/styles/main.css
@@ -0,0 +1,208 @@
+.browsehappy {
+ margin: 0.2em 0;
+ background: #ccc;
+ color: #000;
+ padding: 0.2em 0;
+}
+
+body {
+ padding: 0;
+}
+
+
+/* Everything but the jumbotron gets side spacing for mobile first views */
+
+.header,
+.marketing,
+.footer {
+ /*padding-left: 15px;
+ padding-right: 15px;*/
+}
+
+
+/* Custom page header */
+
+.header {
+ border-bottom: 1px solid #e5e5e5;
+ margin-bottom: 10px;
+}
+
+
+/* Make the masthead heading the same height as the navigation */
+
+.header h3 {
+ margin-top: 0;
+ margin-bottom: 0;
+ line-height: 40px;
+ padding-bottom: 19px;
+}
+
+
+/* Custom page footer */
+
+.footer {
+ padding-top: 19px;
+ color: #777;
+ border-top: 1px solid #e5e5e5;
+}
+
+.container-narrow>hr {
+ margin: 30px 0;
+}
+
+
+/* Main marketing message and sign up button */
+
+.jumbotron {
+ text-align: center;
+ border-bottom: 1px solid #e5e5e5;
+}
+
+.jumbotron .btn {
+ font-size: 21px;
+ padding: 14px 24px;
+}
+
+
+/* Supporting marketing content */
+
+.marketing {
+ margin: 40px 0;
+}
+
+.marketing p+h4 {
+ margin-top: 28px;
+}
+
+
+/* Responsive: Portrait tablets and up */
+
+@media screen and (min-width: 768px) {
+ .container {
+ max-width: 730px;
+ }
+ /* Remove the padding we set earlier */
+ .header,
+ .marketing,
+ .footer {
+ padding-left: 0;
+ padding-right: 0;
+ }
+ /* Space out the masthead */
+ .header {
+ margin-bottom: 30px;
+ }
+ /* Remove the bottom border on the jumbotron for visual effect */
+ .jumbotron {
+ border-bottom: 0;
+ }
+}
+
+.jumbotron.ng-scope {
+ margin-top: 100px;
+}
+
+.content {
+ /*margin-left: 300px;*/
+ /*margin-left: 100px;*/
+ position: relative;
+ margin-left: 25%;
+ width: 70%;
+ border: 1px solid #dfe3e4;
+ border-radius: 5px;
+ padding: 20px 20px 5px 20px;
+ height: 100%;
+ margin-right: 10px;
+ /*border-bottom: none;*/
+ margin-bottom: 10px;
+ padding-bottom: 20px;
+ /* overflow: hidden; */
+}
+
+.ngdialog.ngdialog-theme-default .ngdialog-content {
+ background-color: #fff;
+}
+
+.progree-parent {
+ width: 50%;
+ background-color: #dfe3e4;
+ height: 10px;
+ border-radius: 10px;
+}
+
+.progree-child {
+ width: 50%;
+ background-color: #2ecc71;
+ /* background-color: white; */
+ height: 10px;
+ border-radius: 5px;
+}
+
+textarea {
+ width: 100%;
+ height: 400px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+}
+
+.naviSide {
+ position: fixed;
+ left: 0px;
+ top: 0px;
+ height: 150%;
+ background-color: #f8f8f8;
+ width: 210px;
+ padding: 30px 0 0 0;
+ border-radius: 10px;
+ border-right: 1px solid #e7e7e7;
+ z-index: 2;
+}
+
+.panel-body {
+ border: none;
+}
+
+.panel-group {
+ width: 210px;
+}
+
+.panel-group {
+ margin-bottom: 0px;
+}
+
+* {
+ border-radius: 0px ! important;
+}
+
+.naviSide.ng-scope {
+ box-shadow: 1px 1px 2px #888888;
+}
+
+.pagination>li>a,
+.pagination>li>span {
+ color: #333;
+}
+
+.pagination>.active>a,
+.pagination>.active>span,
+.pagination>.active>a:hover,
+.pagination>.active>span:hover,
+.pagination>.active>a:focus,
+.pagination>.active>span:focus {
+ background-color: #f9f9f9;
+ color: #333;
+ border-color: #ddd;
+}
+
+.ngdialog.ngdialog-theme-default .ngdialog-close{
+ border: none;
+ background-color: #fff;
+}
+
+button:focus {outline:0;}
+input:focus{outline: 0}
+
+.ngdialog-content {
+ overflow: hidden;
+}
+
diff --git a/gui/app/views/container.html b/gui/app/views/container.html
new file mode 100644
index 000000000..b3d78bfb1
--- /dev/null
+++ b/gui/app/views/container.html
@@ -0,0 +1,134 @@
+<!--container management-->
+
+<div class="content">
+ <div style="display:flex;flex-direction:row;">
+ <div style="width:750px;">
+
+ <h3>{{envName}} -- Container
+ <!--<button class="btn btn-default" style="float:right">Go Next</button>-->
+
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+
+ <hr/>
+
+ <select ng-model="selectContainer" data-ng-options="container as container.name for container in containerList">
+ <option value="">Choose...</option>
+ </select>
+
+ <button class="btn btn-default" ng-click="createContainer()" ng-disabled="selectContainer==null">
+ <div ng-show="!showloading">Create</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="showloading" />
+ </button>
+
+ <hr/>
+
+ <div>
+ <h4 ng-show="displayContainerInfo.length==0">No Container Data</h4>
+ <div ng-show="displayContainerInfo.length!=0">
+ <h4>Current Container</h4>
+ <table class="table table-striped">
+
+ <tr>
+ <th>name</th>
+ <th>status</th>
+ <th>time</th>
+ <th>delete</th>
+
+ </tr>
+ <tr ng-repeat="con in displayContainerInfo">
+ <td>{{con.name}}</td>
+ <td>{{con.status}}</td>
+ <td>{{con.time}}</td>
+ <td>
+ <button class="btn btn-default btn-sm" ng-click="openDeleteEnv(con.id,'container')">Delete</button>
+ </td>
+
+
+ </tr>
+
+
+
+ </table>
+ </div>
+ </div>
+
+
+
+
+
+
+
+
+
+
+ </div>
+
+
+ </div>
+
+</div>
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 200px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ font-size: 12px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 15px;
+ height: 15px;
+ opacity: 0.8;
+ margin-left: -10px;
+ margin-top: -3px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ select {
+ height: 30px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ width: 135px;
+ margin-top: 20px;
+ margin-left: 20px;
+ }
+</style>
diff --git a/gui/app/views/content.html b/gui/app/views/content.html
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/gui/app/views/content.html
diff --git a/gui/app/views/environmentDetail.html b/gui/app/views/environmentDetail.html
new file mode 100644
index 000000000..4d5f21c68
--- /dev/null
+++ b/gui/app/views/environmentDetail.html
@@ -0,0 +1,143 @@
+<!--environment detail page-->
+
+<div class="content" style="overflow-x: scroll;">
+ <div style="display:flex;flex-direction:row;">
+ <div>
+
+
+ <h3> {{baseElementInfo.name}} -- Openrc
+ <button class="btn btn-default" style="float:right" ng-click="goNext()">Next</button>
+ <button class="btn btn-default" style="float:right;margin-right:10px;" ng-click="openDeleteEnv(1,'openrc')">Delete</button>
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+
+
+
+ <div>
+
+ <button style="display:inline;" class="btn btn-default" ng-click="addEnvironment()" ng-show="uuid==null">Add Name</button>
+ </div>
+
+
+
+ <hr/>
+ <div bs-tabs style="width:600px;">
+ <div data-title="Detail" bs-pane ng-if="openrcInfo.openrc!=null">
+
+ <h4>
+ You have already set up the openrc parameters
+ </h4>
+ <hr />
+ <div ng-repeat="(key,value) in openrcInfo.openrc">
+ <nobr>
+ <font style="font-weight:600;font-size:14px;">{{key}} : </font>
+ <font style="font-size:14px;">{{value}}</font>
+ </nobr>
+ </div>
+
+ </div>
+ <div data-title="Update" bs-pane>
+
+ <div style="margin-top:20px;">
+ <button class="btn btn-default" ng-click="addInfo()" style="margin-bottom:20px;">Add</button>
+ <div style="height:300px;width:800px;display:flex;flex-direction:column;flex-wrap:wrap;margin-left:5px;">
+ <div ng-repeat="info in envInfo">
+ <!--<div> {{info.name}}</div>-->
+
+ <input class="edit-title" ng-model="info.name" ng-class="{'null-edit-title':info.name==null}" ng-attr-type="{{info.name.indexOf('PASSWORD')>-1 ? password : text}}" />
+
+ <div class="item-info">
+ <input class="form-control" type="text" ng-model="info.value" />
+ <!--<button class="delete-button" ng-click="deleteEnvItem($index)">delete</button>-->
+ <img src="images/close.png" ng-click="deleteEnvItem($index)" class="delete-img" />
+ </div>
+
+
+
+ </div>
+ </div>
+ <button class="btn btn-default" ng-click="submitOpenRcFile()" style="margin-bottom:20px;">
+ <div ng-if="!showloading">submit</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="showloading" />
+ </button>
+
+ </div>
+
+ </div>
+ <div data-title="Upload File" bs-pane>
+ <div style="margin-top:20px;height:405px;">
+ <button class="btn btn-default" style="margin-bottom:20px;" ngf-select="uploadFiles($file, $invalidFiles)" ngf-max-size="5MB">
+ <div ng-show="!loadingOPENrc">Upload</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="loadingOPENrc" />
+ </button>
+
+ <!--<div ng-show="displayOpenrcFile!=null || displayOpenrcFile!=undefined">
+ {{displayOpenrcFile.name}} last modified: {{filelastModified}}
+ </div>-->
+ </div>
+ </div>
+ </div>
+
+
+
+ </div>
+
+
+ </div>
+
+</div>
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 200px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ font-size: 12px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 15px;
+ height: 15px;
+ opacity: 0.8;
+ margin-left: -10px;
+ margin-top: -3px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+</style>
diff --git a/gui/app/views/environmentList.html b/gui/app/views/environmentList.html
new file mode 100644
index 000000000..29273a724
--- /dev/null
+++ b/gui/app/views/environmentList.html
@@ -0,0 +1,155 @@
+<div class="content">
+
+ <!--environmentList-->
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+
+ <div>
+
+ <h3>Environments
+ <button class="btn btn-default btn-sm" style="margin-left:30px;display:inline" ng-click="openEnvironmentDialog()">Add</button>
+ </h3>
+ <hr/>
+
+ <!--<div ng-repeat="env in environmentList">
+ {{env.name}}
+ </div>-->
+ <div dw-loading="key" dw-loading-options="{text:'loading'}">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;background-color: #f9f9f9;">
+ <div style="font-weight:600">Name</div>
+ <div style="font-weight:600;margin-right:80px;">Action</div>
+
+ </div>
+
+ <div dir-paginate="env in environmentList | orderBy:'-id' | itemsPerPage: 10 ">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;">
+ <div> <a style="color:#e95420" ng-click="gotoDetail('false',env.uuid)">{{env.name}}</a></div>
+ <div>
+
+ <!-- <button class="btn btn-default btn-sm" ng-click="openDeleteEnv(env.uuid,'environment')">Delete</button> -->
+
+ <div class="btn-group" uib-dropdown is-open="status.isopen" style="margin-right:60px;">
+ <button id="single-button" type="button" class="btn btn-default btn-sm" uib-dropdown-toggle>
+ Modify <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
+ <li role="menuitem"><a ng-click="openDeleteEnv(env.uuid,'environment')">Delete</a></li>
+ <!-- <li role="menuitem"><a href="#">Another action</a></li>
+ <li role="menuitem"><a href="#">Something else here</a></li>
+ <li class="divider"></li>
+ <li role="menuitem"><a href="#">Separated link</a></li> -->
+ </ul>
+ </div>
+ </div>
+
+
+
+ </div>
+
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+ </div>
+
+
+
+
+
+
+
+ </div>
+
+
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 19px;
+ height: 19px;
+ opacity: 0.8;
+ margin-left: 5px;
+ margin-top: 4px;
+ cursor: pointer;
+ }
+
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/app/views/layout/footer.html b/gui/app/views/layout/footer.html
new file mode 100644
index 000000000..cfdf74af3
--- /dev/null
+++ b/gui/app/views/layout/footer.html
@@ -0,0 +1,5 @@
+<div class="footer">
+ <div class="container">
+ <p></p>
+ </div>
+</div> \ No newline at end of file
diff --git a/gui/app/views/layout/header.html b/gui/app/views/layout/header.html
new file mode 100644
index 000000000..033322a62
--- /dev/null
+++ b/gui/app/views/layout/header.html
@@ -0,0 +1,43 @@
+<div class="header">
+ <div class="navbar navbar-default" role="navigation">
+ <div>
+ <div class="navbar-header">
+
+
+
+ <a class="navbar-brand" href="#/">Yardstick</a>
+ </div>
+
+
+ </div>
+ </div>
+</div>
+</div>
+
+<style>
+ .header {
+ position: fixed;
+ top: 0px;
+ width: 100%;
+ /*box-shadow: 3px 2px 5px #888888;*/
+ z-index: 9;
+ }
+
+ .navbar {
+ position: relative;
+ min-height: 50px;
+ margin-bottom: 0px;
+ border: none;
+ /* border: 1px solid transparent; */
+ }
+
+ .navbar {
+ border-radius: 0px;
+ background-color: #e95420;
+ color: #fff;
+ }
+
+ .navbar-default .navbar-brand {
+ color: #fff;
+ }
+</style>
diff --git a/gui/app/views/layout/sideNav.html b/gui/app/views/layout/sideNav.html
new file mode 100644
index 000000000..42dcbbc6e
--- /dev/null
+++ b/gui/app/views/layout/sideNav.html
@@ -0,0 +1,141 @@
+<div class="naviSide">
+
+
+
+
+ <ul class="nav bs-sidenav">
+
+ <div class="panel-group " role="tablist " aria-multiselectable="true " bs-collapse style="margin-bottom:0px; ">
+ <div class="panel panel-default ">
+ <div class="panel-heading " role="tab ">
+ <h4 class="panel-title ">
+ <a bs-collapse-toggle style=" text-decoration: none;" ng-click="gotoProject();">
+ Project
+ </a>
+ </h4>
+
+ </div>
+
+ </div>
+ </div>
+ <div class="panel-group" role="tablist" aria-multiselectable="true" bs-collapse style="margin-bottom:0px;" ng-model="activeStatus">
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a bs-collapse-toggle style=" text-decoration: none;">
+ <div style="display:inline;" ng-click="gotoEnviron()">Environment </div>
+ <i class="fa fa-sort-asc" aria-hidden="true" style="margin-left: 71px;display:inline" ng-show="activeStatus==0"></i>
+ <i class="fa fa-sort-desc" aria-hidden="true" style="margin-left: 71px;display:inline" ng-show="activeStatus==-1"></i>
+ </a>
+ </h4>
+ </div>
+ <div class="panel-collapse" role="tabpanel" bs-collapse-target>
+ <div class="panel-body" style="border-top: 2px solid grey;text-align: right;cursor:pointer" ng-click="gotoOpenrcPage()" ng-class="{active:$state.includes('app.environmentDetail')}">
+ Openrc
+ </div>
+ <div class="panel-body " style="border:none;text-align: right;cursor:pointer" ng-click="gotoUploadPage()" ng-class="{active:$state.includes('app.uploadImage')}">
+ Image
+ </div>
+ <div class="panel-body " style="border:none;text-align: right;cursor:pointer" ng-click="gotoPodPage()" ng-class="{active:$state.includes('app.podUpload')}">
+ Pod File
+ </div>
+ <div class="panel-body " style="border:none;text-align: right;cursor:pointer" ng-click="gotoContainerPage()" ng-class="{active:$state.includes('app.container')}">
+ Container
+ </div>
+ <div class="panel-body " style="border:none;text-align: right;">
+ Others
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="panel-group " role="tablist " aria-multiselectable="true " bs-collapse style="margin-bottom:0px; ">
+ <div class="panel panel-default ">
+ <div class="panel-heading " role="tab ">
+ <h4 class="panel-title ">
+ <a bs-collapse-toggle style=" text-decoration: none;" ng-click="gotoTestcase()">
+ Test Case
+ </a>
+ </h4>
+
+ </div>
+
+ </div>
+ </div>
+
+ <div class="panel-group " role="tablist " aria-multiselectable="true " bs-collapse style="margin-bottom:0px; ">
+ <div class="panel panel-default ">
+ <div class="panel-heading " role="tab ">
+ <h4 class="panel-title ">
+ <a bs-collapse-toggle style=" text-decoration: none;" ng-click="gotoSuite()">
+ Test Suite
+ </a>
+ </h4>
+
+ </div>
+
+ </div>
+ </div>
+
+
+
+ </ul>
+
+
+
+
+
+</div>
+
+
+<style>
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .naviSide {
+ height: 150%;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ width: 165px;
+ }
+ /*
+ a:hover {
+ width: 165px;
+ }*/
+
+ .nav>li>a:hover,
+ .nav>li>a:focus {
+ text-decoration: underline;
+ background-color: transparent;
+ }
+
+ .active.panel-body {
+ background-color: #dfe3e4;
+ }
+</style>
diff --git a/gui/app/views/layout/sideNav2.html b/gui/app/views/layout/sideNav2.html
new file mode 100644
index 000000000..104a9c6cf
--- /dev/null
+++ b/gui/app/views/layout/sideNav2.html
@@ -0,0 +1,108 @@
+<div class="naviSide">
+
+
+ <ul class="nav bs-sidenav">
+
+ <div class="panel-group " role="tablist " aria-multiselectable="true " bs-collapse style="margin-bottom:0px; ">
+ <div class="panel panel-default ">
+ <div class="panel-heading " role="tab ">
+ <h4 class="panel-title ">
+ <a bs-collapse-toggle style=" text-decoration: none;" ng-click="gotoProject();">
+ Project
+ </a>
+ </h4>
+
+ </div>
+
+ </div>
+ </div>
+ <div class="panel-group" role="tablist" aria-multiselectable="false" bs-collapse style="margin-bottom:0px;">
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab">
+ <h4 class="panel-title">
+ <a bs-collapse-toggle style=" text-decoration: none;">
+ <div style="display:inline;" ng-click="gotoEnviron()">Environment </div>
+ <!--<i class="fa fa-sort-asc" aria-hidden="true" style="margin-left: 71px;display:inline"></i>-->
+ </a>
+ </h4>
+ </div>
+
+ </div>
+ </div>
+
+ <div class="panel-group " role="tablist " aria-multiselectable="true " bs-collapse style="margin-bottom:0px; ">
+ <div class="panel panel-default ">
+ <div class="panel-heading " role="tab ">
+ <h4 class="panel-title ">
+ <a bs-collapse-toggle style=" text-decoration: none;" ng-click="gotoTestcase()">
+ Test Case
+ </a>
+ </h4>
+
+ </div>
+
+ </div>
+ </div>
+
+ <div class="panel-group " role="tablist " aria-multiselectable="true " bs-collapse style="margin-bottom:0px; ">
+ <div class="panel panel-default ">
+ <div class="panel-heading " role="tab ">
+ <h4 class="panel-title ">
+ <a bs-collapse-toggle style=" text-decoration: none;" ng-click="gotoSuite()">
+ Test Suite
+ </a>
+ </h4>
+
+ </div>
+
+ </div>
+ </div>
+
+
+
+ </ul>
+
+</div>
+
+<style>
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ width: 165px;
+ }
+ /*a:hover {
+ width: 165px;
+ }*/
+
+ .nav>li>a:hover,
+ .nav>li>a:focus {
+ text-decoration: underline;
+ background-color: transparent;
+ }
+</style>
diff --git a/gui/app/views/main.html b/gui/app/views/main.html
new file mode 100644
index 000000000..d5f7a3af3
--- /dev/null
+++ b/gui/app/views/main.html
@@ -0,0 +1,174 @@
+<div>
+ <div ng-include="'views/layout/header.html'"></div>
+</div>
+<div ng-include="'views/layout/sideNav.html'"></div>
+
+
+<div style="margin-top:80px;margin-left:100px;display:flex;flex-direction:row">
+ <!--<div ncy-breadcrumb></div>-->
+ <div>
+ <ol class="progressDefine">
+ <li data-step="1" ng-click="gotoProject();" style="cursor:pointer" ng-class="{'is-complete':projectShow}">
+ Project
+ </li>
+ <li data-step="2" ng-class="{'is-complete':taskShow}">
+ Task
+ </li>
+
+ <li data-step="3" ng-class="{'progressDefine__last':reportShow}">
+ Reporting
+ </li>
+
+ </ol>
+ </div>
+
+
+</div>
+
+
+
+
+
+
+
+
+
+<div ui-view></div>
+
+
+
+<style>
+ .stepsContent {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ margin-left: 120px;
+ margin-top: 100px;
+ }
+
+ .stepItem {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .nextButton {
+ margin-left: 500px;
+ }
+
+ .progressDefine {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+ color: #849397;
+ }
+
+ .progressDefine>li {
+ position: relative;
+ display: table-cell;
+ text-align: center;
+ font-size: 0.8em;
+ }
+
+ .progressDefine>li:before {
+ content: attr(data-step);
+ display: block;
+ margin: 0 auto;
+ background: #DFE3E4;
+ width: 3em;
+ height: 3em;
+ text-align: center;
+ margin-bottom: 0.25em;
+ line-height: 3em;
+ border-radius: 100%;
+ position: relative;
+ z-index: 5;
+ }
+
+ .progressDefine>li:after {
+ content: '';
+ position: absolute;
+ display: block;
+ background: #DFE3E4;
+ width: 100%;
+ height: 0.5em;
+ top: 1.25em;
+ left: 50%;
+ margin-left: 1.5em\9;
+ z-index: -1;
+ }
+
+ .progressDefine>li:last-child:after {
+ display: none;
+ }
+
+ .progressDefine>li.is-complete {
+ color: #e95420;
+ }
+
+ .progressDefine>li.is-complete:before,
+ .progressDefine>li.is-complete:after {
+ color: #FFF;
+ background: #e95420;
+ }
+
+ .progressDefine>li.is-active {
+ color: #3498DB;
+ }
+
+ .progressDefine>li.is-active:before {
+ color: #FFF;
+ background: #3498DB;
+ }
+ /**
+ * Needed for IE8
+ */
+
+ .progressDefine__last:after {
+ display: none !important;
+ }
+ /**
+ * Size Extensions
+ */
+
+ .progressDefine--medium {
+ font-size: 1.5em;
+ }
+
+ .progressDefine--large {
+ font-size: 2em;
+ }
+ /**
+ * Some Generic Stylings
+ */
+
+ *,
+ *:after,
+ *:before {
+ box-sizing: border-box;
+ }
+
+ h1 {
+ margin-bottom: 1.5em;
+ }
+
+ .progressDefine {
+ margin-bottom: 3em;
+ }
+
+ a {
+ color: #3498DB;
+ text-decoration: none;
+ }
+
+ a:hover {
+ text-decoration: underline;
+ }
+ /*
+ body {
+ text-align: center;
+ color: #444;
+ }*/
+</style>
diff --git a/gui/app/views/main2.html b/gui/app/views/main2.html
new file mode 100644
index 000000000..661d604c6
--- /dev/null
+++ b/gui/app/views/main2.html
@@ -0,0 +1,174 @@
+<div>
+ <div ng-include="'views/layout/header.html'"></div>
+</div>
+<div ng-include="'views/layout/sideNav2.html'"></div>
+
+
+<div style="margin-top:80px;margin-left:220px;">
+ <!--<div ncy-breadcrumb></div>-->
+ <div>
+ <ol class="progressDefine">
+ <li data-step="1" ng-click="gotoProject();" style="cursor:pointer" ng-class="{'is-complete':projectShow}">
+ Project
+ </li>
+ <li data-step="2" ng-class="{'is-complete':taskShow}">
+ Task
+ </li>
+
+ <li data-step="3" ng-class="{'is-complete':reportShow}">
+ Reporting
+ </li>
+
+ </ol>
+ </div>
+
+
+</div>
+
+
+
+
+
+
+
+
+
+<div ui-view></div>
+
+
+
+<style>
+ .stepsContent {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ margin-left: 120px;
+ margin-top: 100px;
+ }
+
+ .stepItem {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .nextButton {
+ margin-left: 500px;
+ }
+
+ .progressDefine {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+ color: #849397;
+ }
+
+ .progressDefine>li {
+ position: relative;
+ display: table-cell;
+ text-align: center;
+ font-size: 0.8em;
+ }
+
+ .progressDefine>li:before {
+ content: attr(data-step);
+ display: block;
+ margin: 0 auto;
+ background: #DFE3E4;
+ width: 3em;
+ height: 3em;
+ text-align: center;
+ margin-bottom: 0.25em;
+ line-height: 3em;
+ border-radius: 100%;
+ position: relative;
+ z-index: 5;
+ }
+
+ .progressDefine>li:after {
+ content: '';
+ position: absolute;
+ display: block;
+ background: #DFE3E4;
+ width: 100%;
+ height: 0.5em;
+ top: 1.25em;
+ left: 50%;
+ margin-left: 1.5em\9;
+ z-index: -1;
+ }
+
+ .progressDefine>li:last-child:after {
+ display: none;
+ }
+
+ .progressDefine>li.is-complete {
+ color: #e95420;
+ }
+
+ .progressDefine>li.is-complete:before,
+ .progressDefine>li.is-complete:after {
+ color: #FFF;
+ background: #e95420;
+ }
+
+ .progressDefine>li.is-active {
+ color: #3498DB;
+ }
+
+ .progressDefine>li.is-active:before {
+ color: #FFF;
+ background: #3498DB;
+ }
+ /**
+ * Needed for IE8
+ */
+
+ .progressDefine__last:after {
+ display: none !important;
+ }
+ /**
+ * Size Extensions
+ */
+
+ .progressDefine--medium {
+ font-size: 1.5em;
+ }
+
+ .progressDefine--large {
+ font-size: 2em;
+ }
+ /**
+ * Some Generic Stylings
+ */
+
+ *,
+ *:after,
+ *:before {
+ box-sizing: border-box;
+ }
+
+ h1 {
+ margin-bottom: 1.5em;
+ }
+
+ .progressDefine {
+ margin-bottom: 3em;
+ }
+
+ a {
+ color: #3498DB;
+ text-decoration: none;
+ }
+
+ a:hover {
+ text-decoration: underline;
+ }
+ /*
+ body {
+ text-align: center;
+ color: #444;
+ }*/
+</style>
diff --git a/gui/app/views/modal/chooseContainer.html b/gui/app/views/modal/chooseContainer.html
new file mode 100644
index 000000000..4b857b22f
--- /dev/null
+++ b/gui/app/views/modal/chooseContainer.html
@@ -0,0 +1,15 @@
+<h3>Choose Containers</h3>
+<hr/>
+
+
+
+<style>
+ select {
+ height: 30px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ width: 135px;
+ margin-top: 20px;
+ margin-left: 20px;
+ }
+</style> \ No newline at end of file
diff --git a/gui/app/views/modal/deleteConfirm.html b/gui/app/views/modal/deleteConfirm.html
new file mode 100644
index 000000000..1659b884b
--- /dev/null
+++ b/gui/app/views/modal/deleteConfirm.html
@@ -0,0 +1,19 @@
+<div>Confirm delete {{deleteName}} ?</div>
+
+<div style="display:flex;flex-direction:row; margin-left: 150px;margin-top: 30px;">
+ <button class="btn btn-default" ng-click="deleteEnv()" ng-show="deleteName=='environment'">Confirm</button>
+ <button class="btn btn-default" ng-click="deleteProject()" ng-show="deleteName=='project'">Confirm</button>
+ <button class="btn btn-default" ng-click="deleteTask()" ng-show="deleteName=='task'">Confirm</button>
+ <button class="btn btn-default" ng-click="deleteTestCase()" ng-show="deleteName=='test case'">Confirm</button>
+ <button class="btn btn-default" ng-click="deleteSuite()" ng-show="deleteName=='test suite'">Confirm</button>
+ <button class="btn btn-default" ng-click="deleteContainer()" ng-show="deleteName=='container'">Confirm</button>
+ <button class="btn btn-default" ng-click="deletePod()" ng-show="deleteName=='pod'">Confirm</button>
+ <button class="btn btn-default" ng-click="deleteOpenRc()" ng-show="deleteName=='openrc'">Confirm</button>
+
+
+
+
+
+ <button class="btn btn-default" style="margin-left:10px;" ng-click="closeThisDialog()">Cancel</button>
+
+</div> \ No newline at end of file
diff --git a/gui/app/views/modal/environmentDialog.html b/gui/app/views/modal/environmentDialog.html
new file mode 100644
index 000000000..a5b88d240
--- /dev/null
+++ b/gui/app/views/modal/environmentDialog.html
@@ -0,0 +1,330 @@
+<!--environment input dialog-->
+
+<div>
+ <div ng-if="uuidEnv==null">
+ <h4>Environment Name</h4>
+ <input type="text" ng-model="name" style="width:300px;" />
+
+ <div style="text-align:center;margin-top:20px;">
+ <button class="btn btn-default" ng-disabled=" name==null || name==''" ng-click="addEnvironment(name)">Create</button>
+ </div>
+ </div>
+
+
+ <div style="display:flex;flex-direction:row;" ng-if="uuidEnv!=null&&showImage==null">
+ <div>
+ <h3> {{name}} -- Openrc
+ <!--<button class="btn btn-default" style="float:right" ng-click="goNext()">Next</button>-->
+ <button class="btn btn-default" ng-click="goToImage()" style="margin-bottom:20px;float:right" ng-disabled="showNextOpenRc==null && showNextOpenRc==null ">
+ Next
+ </button>
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+ <div>
+
+ <!--<button style="display:inline;" class="btn btn-default" ng-click="addEnvironment()" ng-show="uuid==null">Add Name</button>-->
+ </div>
+
+ <hr/>
+ <div bs-tabs style="width:750px;">
+ <div data-title="Detail" bs-pane ng-if="openrcInfo.openrc!=null">
+
+ <h4>
+ You have already set up the openrc parameters
+ </h4>
+ <hr />
+ <div ng-repeat="(key,value) in openrcInfo.openrc">
+ <nobr>
+ <font style="font-weight:600;font-size:14px;">{{key}} : </font>
+ <font style="font-size:14px;">{{value}}</font>
+ </nobr>
+ </div>
+
+ </div>
+ <div data-title="Update" bs-pane>
+
+ <div style="margin-top:20px;">
+ <button class="btn btn-default" ng-click="addInfo()" style="margin-bottom:20px;">Add</button>
+ <div style="height:300px;width:800px;display:flex;flex-direction:column;flex-wrap:wrap;margin-left:5px;overflow-x:scroll">
+ <div ng-repeat="info in envInfo">
+ <!--<div> {{info.name}}</div>-->
+
+ <input class="edit-title" ng-model="info.name" ng-class="{'null-edit-title':info.name==null}" ng-attr-type="{{info.name.indexOf('PASSWORD')>-1 ? password : text}}" />
+
+ <div class="item-info">
+ <input class="form-control" type="text" ng-model="info.value" />
+ <!--<button class="delete-button" ng-click="deleteEnvItem($index)">delete</button>-->
+ <img src="images/close.png" ng-click="deleteEnvItem($index)" class="delete-img" />
+ </div>
+
+
+
+ </div>
+ </div>
+ <button class="btn btn-default" ng-click="submitOpenRcFile();" style="margin-bottom:20px;">
+ <div ng-if="!showloading">Submit</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="showloading" />
+ </button>
+
+
+ </div>
+
+ </div>
+ <div data-title="Upload File" bs-pane>
+ <div style="margin-top:20px;height:405px;">
+ <button class="btn btn-default" style="margin-bottom:20px;" ngf-select="uploadFiles($file, $invalidFiles);" ngf-max-size="5MB">
+ <div ng-show="!loadingOPENrc">Upload</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="loadingOPENrc" />
+ </button>
+ <!--<button class="btn btn-default" style="margin-bottom:20px;" ng-disabled="showNextOpenRc==null" ng-click="goToImage()">
+ Next
+ </button>-->
+
+ <!--<div ng-if="displayOpenrcFile!=null || displayOpenrcFile!=undefined">
+ {{displayOpenrcFile.name}} last modified: {{filelastModified}}
+ </div>-->
+ </div>
+ </div>
+ </div>
+
+
+
+ </div>
+
+
+ </div>
+
+ <div ng-if="showImage==1&&showPod==null">
+ <div style="display:flex;flex-direction:row;">
+ <div style="width:750px;">
+
+ <h3>{{name}} -- Image
+
+ <button class="btn btn-default" ng-click="goToPod()" ng-disabled="showNextPod==null" style="float:right">
+ Next
+ </button>
+ <button class="btn btn-default" ng-click="goToPodPrev()" style="margin-right:5px;float:right">
+ Previous
+ </button>
+
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+
+ <hr/>
+
+ <button class="btn btn-default" ng-click="uploadImage()">
+ <div ng-if="!showloading">Load Image</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="showloading" />
+
+ </button>
+
+ <i class="fa fa-check" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: #2ecc71;" ng-show="imageStatus==1&&showImageStatus==1">done</i>
+ <i class="fa fa-spinner" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: #2ecc71;" ng-show="imageStatus==0&&showImageStatus==1">loading</i>
+ <i class="fa fa-exclamation-triangle" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: red;" ng-show="imageStatus==2&&showImageStatus==1">error</i>
+
+
+ <!--<button class="btn btn-default" ng-click="goToPod()" ng-disabled="showNextPod==null">
+ Next
+ </button>-->
+ <hr>
+ <h4>Current Images</h4>
+
+ <div>
+ <table class="table table-striped">
+
+ <tr>
+ <th>name</th>
+ <th>size</th>
+ <th>status</th>
+ <th>time</th>
+ </tr>
+ <tr ng-repeat="image in imageListData">
+ <td>{{image.name}}</td>
+ <td>{{image.size/1024}} mb</td>
+ <td>{{image.status}}</td>
+ <td>{{image.time}}</td>
+
+ </tr>
+
+
+
+ </table>
+ </div>
+
+
+ </div>
+
+
+ </div>
+ </div>
+
+ <div ng-if="showPod==1&&showContainer==null">
+ <div style="display:flex;flex-direction:row;">
+ <div style="width:750px;">
+
+
+ <h3>{{name}} -- Pod File
+ <div style="float:right">
+ <button class="btn btn-default" ng-click="skipPodPrev()">Previous</button>
+ <button class="btn btn-default" ng-click="skipPod()" ng-show="podData==null">Skip</button>
+ <button class="btn btn-default" ng-click="skipPod()" ng-show="podData!=null">Next</button>
+
+ </div>
+
+ </h3>
+
+ <hr/>
+
+ <button class="btn btn-default" ngf-select="uploadFilesPod($file, $invalidFiles)" ngf-max-size="5MB">
+ <div ng-show="!loadingOPENrc">Upload</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="loadingOPENrc" />
+ </button>
+
+
+ <hr/>
+
+ <div>
+ <h4>Current Pod Configuration</h4>
+ <table class="table table-striped">
+
+ <tr>
+ <th>ip</th>
+ <th>name</th>
+ <th>password</th>
+ <th>role</th>
+ <th>user</th>
+ </tr>
+ <tr ng-repeat="pod in podData.pod.nodes">
+ <td>{{pod.ip}}</td>
+ <td>{{pod.name}}</td>
+ <td>{{pod.password}}</td>
+ <td>{{pod.role}}</td>
+ <td>{{pod.user}}</td>
+
+ </tr>
+ <tr ng-show="podData.length==0">
+ <td>no data</td>
+
+ </tr>
+
+
+
+ </table>
+ </div>
+
+
+
+
+
+
+
+
+
+
+ </div>
+
+
+ </div>
+
+ </div>
+
+ <div ng-if="showContainer!=null">
+ <div style="display:flex;flex-direction:row;">
+ <div style="width:750px;">
+
+ <h3>{{name}} -- Container
+ <div style="float:right">
+ <button class="btn btn-default" ng-click="skipContainerPrev()">Previous</button>
+ <button class="btn btn-default" ng-click="skipContainer()" ng-show="ifskipOrClose!=1">
+ Skip
+ </button>
+ <button class="btn btn-default" ng-click="closeThisDialog(); getEnvironmentList();" ng-show="ifskipOrClose==1">
+ Close
+ </button>
+ </div>
+ <!--<button class="btn btn-default" style="float:right">Go Next</button>-->
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+
+ <hr/>
+
+ <select ng-model="selectContainer" data-ng-options="container as container.name for container in containerList">
+ <option value="">Choose...</option>
+ </select>
+
+ <button class="btn btn-default" ng-click="createContainer(selectContainer)" ng-disabled="selectContainer==null">
+ <div ng-show="!showloading">Create</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="showloading" />
+ </button>
+ <!--<button class="btn btn-default" ng-click="skipContainer()" ng-show="ifskipOrClose!=1">
+ Skip
+ </button>
+ <button class="btn btn-default" ng-click="closeThisDialog(); getEnvironmentList();" ng-show="ifskipOrClose==1">
+ Close
+ </button>-->
+
+ <hr/>
+
+ <div>
+ <h4>Current Contain</h4>
+ <table class="table table-striped">
+
+ <tr>
+ <th>name</th>
+ <th>status</th>
+ <th>time</th>
+
+ </tr>
+ <tr ng-repeat="con in displayContainerInfo">
+ <td>{{con.name}}</td>
+ <td>{{con.status}}</td>
+ <td>{{con.time}}</td>
+
+
+ </tr>
+
+
+
+ </table>
+ </div>
+
+
+
+
+
+
+
+
+
+
+ </div>
+
+
+ </div>
+
+ </div>
+
+
+
+
+
+
+</div>
+
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ }
+
+ select {
+ height: 30px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ width: 135px;
+ margin-top: 20px;
+ margin-left: 20px;
+ }
+</style>
diff --git a/gui/app/views/modal/projectCreate.html b/gui/app/views/modal/projectCreate.html
new file mode 100644
index 000000000..74839e798
--- /dev/null
+++ b/gui/app/views/modal/projectCreate.html
@@ -0,0 +1,21 @@
+<div>
+
+ <h4>Enter Project Name</h4>
+ <input type="text" ng-model="name" />
+
+ <div style="text-align:center;margin-top:20px;">
+ <button class="btn btn-default" ng-disabled=" name==null || name==''" ng-click="createName(name)">Create</button>
+ </div>
+
+
+
+</div>
+
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ }
+</style>
diff --git a/gui/app/views/modal/suiteName.html b/gui/app/views/modal/suiteName.html
new file mode 100644
index 000000000..981d24210
--- /dev/null
+++ b/gui/app/views/modal/suiteName.html
@@ -0,0 +1,18 @@
+<h4>Enter Suite Name</h4>
+<hr/> You have choose:
+<div ng-repeat="selected in suitReconstructList">{{selected}}</div>
+<hr/>
+<input type="text" ng-model="name" />
+
+<div style="text-align:center;margin-top:20px;">
+ <button class="btn btn-default" ng-disabled="testsuiteList.length==0 || name==null || name==''" ng-click="createSuite(name)">Create</button>
+</div>
+
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ }
+</style>
diff --git a/gui/app/views/modal/taskCreate.html b/gui/app/views/modal/taskCreate.html
new file mode 100644
index 000000000..e7812cf2b
--- /dev/null
+++ b/gui/app/views/modal/taskCreate.html
@@ -0,0 +1,134 @@
+
+<h4>Create Task</h4>
+<hr/>
+<div>
+ <div style="display:inline">Name <input type="text" ng-model="name" style="width:200px" /></div>
+ <button style="display:inline" class="btn btn-default" ng-disabled="name==null || name==''" ng-click="createTask(name)" ng-show="newUUID==null">Create</button>
+</div>
+<hr/>
+
+<div bs-tabs ng-show="newUUID!=null">
+ <div data-title="Environment" bs-pane>
+ <div style="margin-top:10px" ng-show="displayEnvName!=null">
+ <div style="display:inline">Choose Environment : {{displayEnvName}}</div>
+ <button class="btn btn-default" style="display:inline;float:right;margin-right:10px;margin-top: -4px;" ng-click="addEnvToTask()">confirm</button>
+ </div>
+ <hr />
+ <div dir-paginate="env in environmentList | orderBy:'-id' | itemsPerPage: 10 ">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;" ng-class="{deepColor: $index%2==0}">
+ <div> {{env.name}}</div>
+ <!--<button class="btn btn-default btn-sm" ng-click="gotoDetail('false',env.uuid)">detail</button>-->
+ <img src="images/checkyes.png" style="height:18px;cursor:pointer" ng-click="constructTestSuit(env.uuid,env.name)" ng-show="selectEnv==env.uuid" />
+ <img src="images/checkno.png" style="height:18px;cursor:pointer" ng-click="constructTestSuit(env.uuid,env.name)" ng-show="selectEnv!=env.uuid" />
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+
+ </div>
+ <div data-title="Content" bs-pane>
+ <div style="display:flex;flex-direction:row">
+ <div style="margin-top:20px;">Source of Content</div>
+
+
+ <select ng-model="selectType" ng-change="triggerContent(selectType)" data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates">
+ <option value="">Choose...</option>
+ </select>
+
+ </div>
+ <div style="margin-top:10px" ng-show="selectCase!=null">
+ <div style="display:inline">Choose Source: {{selectCase}}</div>
+ <button class="btn btn-default" style="display:inline;float:right;margin-right:10px;margin-top: -4px;" ng-click="confirmAddCaseOrSuite(contentInfo)">Confirm</button>
+ <button class="btn btn-default" style="display:inline;float:right;margin-right:10px;margin-top: -4px;" ng-click="getTestDeatil()">Edit</button>
+ </div>
+ <hr/>
+
+ <div ng-show="displayTable==true">
+ <div ng-show="testcaselist.testcases.length!=0 && selectType.name=='Test Case'">
+ <div dir-paginate="test in testcaselist.testcases | itemsPerPage: 10" pagination-id="testcase">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;" ng-class="{deepColor: $index%2==0}">
+ <div> {{test.Name}}</div>
+ <div style="font-size:10px;">{{test.Description}}</div>
+ <img src="images/checkyes.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(test.Name)" ng-show="selectCase==test.Name" />
+ <img src="images/checkno.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(test.Name)" ng-show="selectCase!=test.Name" />
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls pagination-id="testcase"></dir-pagination-controls>
+ </center>
+ </div>
+
+ <div ng-show="testsuitlist.length!=0 && selectType.name=='Test Suite'">
+ <div dir-paginate="suite in testsuitlist | itemsPerPage: 10" pagination-id="testsuite">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;" ng-class="{deepColor: $index%2==0}">
+ <div> {{suite}}</div>
+
+ <img src="images/checkyes.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(suite)" ng-show="selectCase==suite" />
+ <img src="images/checkno.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(suite)" ng-show="selectCase!=suite" />
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls pagination-id="testsuite"></dir-pagination-controls>
+ </center>
+ </div>
+ </div>
+
+ <div ng-show="displayTable==false">
+ <textarea ng-model="contentInfo" spellcheck="false">
+
+
+ </textarea>
+
+
+ </div>
+
+
+
+
+ </div>
+</div>
+
+<div style="text-align:center;margin-top:20px;">
+ <button class="btn btn-default" ng-click="closeThisDialog()" ng-disabled="newUUID===null || ifHasEnv!=true || (ifHasCase!=true && ifHasSuite!=true)">Close</button>
+ <button class="btn btn-default" ng-disabled="newUUID===null || ifHasEnv!=true || (ifHasCase!=true && ifHasSuite!=true)" ng-click="runAtask(newUUID)">Run</button>
+</div>
+
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ }
+
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+
+ select {
+ height: 30px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ width: 135px;
+ margin-top: 20px;
+ margin-left: 20px;
+ }
+
+ textarea {
+ width: 100%;
+ height: 400px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ }
+
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+</style>
diff --git a/gui/app/views/podupload.html b/gui/app/views/podupload.html
new file mode 100644
index 000000000..99e83aca2
--- /dev/null
+++ b/gui/app/views/podupload.html
@@ -0,0 +1,136 @@
+<!--pod file upload-->
+
+<div class="content">
+ <div style="display:flex;flex-direction:row;">
+ <div style="width:750px;">
+ <!--<i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>-->
+
+
+ <h3>{{name}} -- Pod File
+ <button class="btn btn-default" style="float:right" ng-click="goNext()">Next</button>
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+
+ <hr/>
+
+ <button class="btn btn-default" ngf-select="uploadFiles($file, $invalidFiles)" ngf-max-size="5MB">
+ <div ng-show="!loadingOPENrc">Upload</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="loadingOPENrc" />
+ </button>
+ <button class="btn btn-default" ng-click="openDeleteEnv(1,'pod')">Delete</button>
+
+ <!--<div ng-show="displayOpenrcFile!=null || displayOpenrcFile!=undefined ||podData.pod.nodes!=null ">
+ {{displayOpenrcFile.name}} last modified: {{filelastModified}}
+ </div>-->
+
+ <hr/>
+
+ <div>
+ <h4 ng-show="podData.pod.nodes==null">No Pod Configuration</h4>
+ <div ng-show="podData.pod.nodes!=null">
+ <h4>Current Pod Configuration</h4>
+ <table class="table table-striped">
+
+ <tr>
+ <th>ip</th>
+ <th>name</th>
+ <th>password</th>
+ <th>role</th>
+ <th>user</th>
+ </tr>
+ <tr ng-repeat="pod in podData.pod.nodes">
+ <td>{{pod.ip}}</td>
+ <td>{{pod.name}}</td>
+ <td>{{pod.password}}</td>
+ <td>{{pod.role}}</td>
+ <td>{{pod.user}}</td>
+
+ </tr>
+
+
+
+ </table>
+ </div>
+ </div>
+
+
+
+
+
+
+
+
+
+
+ </div>
+ <!--<div style="margin-top:60px;margin-left:67px;">
+ <h3>Openrc parameters</h3>
+ <div>
+ You have already set up the openrc parameters
+ </div>
+ <div ng-repeat="(key,value) in openrcInfo.openrc">
+ <nobr>
+ <font style="font-weight:600;font-size:15px;">{{key}} : </font>
+ <font style="font-size:15px;">{{value}}</font>
+ </nobr>
+ </div>
+ </div>-->
+
+ </div>
+
+</div>
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 200px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ font-size: 12px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 15px;
+ height: 15px;
+ opacity: 0.8;
+ margin-left: -10px;
+ margin-top: -3px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+</style>
diff --git a/gui/app/views/projectList.html b/gui/app/views/projectList.html
new file mode 100644
index 000000000..ea6e63d6b
--- /dev/null
+++ b/gui/app/views/projectList.html
@@ -0,0 +1,57 @@
+<div class="content">
+
+ <h3>Projects
+ <button class="btn btn-default btn-sm" style="margin-left:30px;" ng-click="openCreateProject()">Create</button>
+ </h3>
+
+ <hr/>
+
+
+
+ <div dw-loading="key" dw-loading-options="{text:'loading'}">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;background-color:#f9f9f9;">
+ <div style="font-weight:600">Name</div>
+ <div style="font-weight:600;margin-right:4px;">Action</div>
+
+ </div>
+
+ <div dir-paginate="project in projectListData | orderBy:'-id' | itemsPerPage: 10 ">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;">
+ <div>
+ <a ng-click="gotoDetail(project.uuid)" style="color:#e95420"> {{project.name}}</a>
+ </div>
+ <div>
+ <!-- <button class="btn btn-default btn-sm" ng-click="gotoDetail(project.uuid)">Detail</button> -->
+ <!--<button class="btn btn-default btn-sm" ng-click="openDeleteEnv(project.uuid,'project')">Delete</button>-->
+ <div class="btn-group" uib-dropdown is-open="status.isopen" style="margin-right:20px;">
+ <button id="single-button" type="button" class="btn btn-default btn-sm" uib-dropdown-toggle>
+ Modify <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
+ <li role="menuitem" ng-show="task.status!=0"><a ng-click="openDeleteEnv(project.uuid,'project')">delete</a></li>
+
+
+ </ul>
+ </div>
+ </div>
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+
+ </div>
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+
+<style>
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+</style>
diff --git a/gui/app/views/projectdetail.html b/gui/app/views/projectdetail.html
new file mode 100644
index 000000000..ff61c5fed
--- /dev/null
+++ b/gui/app/views/projectdetail.html
@@ -0,0 +1,97 @@
+<div class="content">
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+
+ <h3>Project -- Task
+
+ </h3>
+
+ <hr/>
+
+ <div>
+
+ <h4>{{projectData.name}}</h4>
+ <h5>{{projectData.time}}</h5>
+ <hr/>
+ <h4>Tasks
+ <button class="btn btn-default btn-sm" style="margin-left:30px;" ng-click="openCreate()">Create</button>
+ </h4>
+ <div ng-show="projectData.tasks.length==0">No task in this project</div>
+ <table class="table " width="100%" dw-loading="key" dw-loading-options="{text:'loading'}">
+ <tr style="background-color:#f9f9f9">
+ <td style="font-weight:700">Name</td>
+ <td style="font-weight:700"> Status</td>
+ <td style="font-weight:700">Action</td>
+ </tr>
+ <tr dir-paginate="task in finalTaskListDisplay | orderBy:'-id' | itemsPerPage: 6 " pagination-id="table">
+
+ <td width="10%"> <a ng-click="gotoDetail(task.uuid)" style="color:#e95420"> {{task.name}} </a></td>
+ <td width="40%">
+ <div class="progree-parent" ng-show="task.status!=2">
+ <div class="progree-child" ng-style="{'width':task.stausWidth}">
+ </div>
+ </div>
+ <div class="progree-parent" ng-show="task.status==2" style="background-color:red">
+ <div class="progree-child" style="width:0">
+ </div>
+ </div>
+ </td>
+
+
+ <td width="50%">
+
+ <div class="btn-group" uib-dropdown is-open="status.isopen" style="margin-right:20px;">
+ <button id="single-button" type="button" class="btn btn-default btn-sm" uib-dropdown-toggle>
+ Modify <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="single-button">
+ <li role="menuitem" ng-show="task.status!=0"><a ng-click="runAtaskForTable(task.uuid)">run</a></li>
+
+ <li role="menuitem" ng-show="task.status!=0"><a ng-click="gotoModify(task.uuid)">modify</a></li>
+ <li role="menuitem" ng-show="task.status!=-1 && task.status!=0"><a ng-click="gotoReport(task.uuid)" style="color:#2ecc71">reporting</a></li>
+ <li role="menuitem"><a ng-click="openDeleteEnv(task.uuid,'task')">delete</a></li>
+
+
+ </ul>
+ </div>
+ <!-- <button class="btn btn-default btn-sm" ng-click="runAtask(task.uuid)" ng-disabled="task.status!=-1">run</button>
+ <button class="btn btn-default btn-sm" ng-click="gotoDetail(task.uuid)">detail</button>
+ <button class="btn btn-default btn-sm" ng-click="gotoModify(task.uuid)" ng-disabled="task.status==0">modify</button>
+ <button class="btn btn-default btn-sm" ng-click="gotoReport(task.uuid)" style="color:#2ecc71" ng-disabled="task.status==-1 || task.status==0">reporting</button>
+ <button class="btn btn-default btn-sm" ng-click="openDeleteEnv(task.uuid,'task')">delete</button> -->
+
+ </td>
+
+ </tr>
+ </table>
+
+
+
+ </div>
+ <center>
+ <dir-pagination-controls pagination-id="table"></dir-pagination-controls>
+ </center>
+
+</div>
+
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+<style>
+ .progree-parent {
+ width: 50%;
+ background-color: #dfe3e4;
+ height: 10px;
+ border-radius: 10px;
+ }
+
+ .progree-child {
+ width: 50%;
+ background-color: #2ecc71;
+ /* background-color: white; */
+ height: 10px;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/app/views/report.html b/gui/app/views/report.html
new file mode 100644
index 000000000..78ac6a0c9
--- /dev/null
+++ b/gui/app/views/report.html
@@ -0,0 +1,56 @@
+<div class="content">
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+ <h3>Yardstick Report </h3>
+ <hr/>
+ <div>
+
+ <div>Task ID : {{result.result.task_id}} </div>
+ <div style="margin-top:5px;">Criteria :
+ <font style="color:#2ECC71" ng-show="result.result.criteria=='PASS'"> {{result.result.criteria}}</font>
+ <font style="color:red" ng-show="result.result.criteria=='FAIL'"> {{result.result.criteria}}</font>
+ </div>
+ <hr/>
+ <caption>Information</caption>
+ <table class="table table-striped">
+ <tr>
+ <th>#</th>
+ <th>key</th>
+ <th>value</th>
+ </tr>
+ <tbody>
+ <tr ng-repeat="(key,value) in result.result.info">
+ <td>{{$index}}</td>
+ <td>{{key}}</td>
+ <td>{{value}}</td>
+ </tr>
+
+ </tbody>
+ </table>
+ <hr/>
+
+ <caption>Test Cases</caption>
+ <table class="table table-striped">
+ <tr>
+ <th>#</th>
+ <th>key</th>
+
+ <th>value</th>
+ <th>grafana</th>
+ </tr>
+ <tbody>
+ <tr ng-repeat="(key,value) in result.result.testcases">
+ <td>{{$index}}</td>
+ <td>{{key}}</td>
+
+ <td>{{value.criteria}}</td>
+ <td> <button class="btn btn-default btn-sm" ng-click="goToExternal(key)"> grafana</button></td>
+ </tr>
+ </tbody>
+ </table>
+
+ </div>
+</div>
+
+
+
+</div>
diff --git a/gui/app/views/suite.html b/gui/app/views/suite.html
new file mode 100644
index 000000000..8e1348333
--- /dev/null
+++ b/gui/app/views/suite.html
@@ -0,0 +1,149 @@
+<div class="content">
+ <!--suitelist-->
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+
+ <div>
+ Test Suites
+ <button class="btn btn-default" style="margin-left:20px;" ng-click="gotoCreateSuite()">
+ Create
+
+ </button>
+
+ <!--<div ng-show="displayOpenrcFile!=null || displayOpenrcFile!=undefined">
+ {{displayOpenrcFile.name}} last modified: {{filelastModified}}
+ </div>-->
+ <hr/>
+
+ <!--<div ng-repeat="env in environmentList">
+ {{env.name}}
+ </div>-->
+ <div dw-loading="key" dw-loading-options="{text:'loading'}">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;background-color: #f9f9f9;" >
+ <div style="font-weight:600">Name</div>
+ <div style="font-weight:600;margin-right:4px;">Operate</div>
+
+ </div>
+
+
+ <div dir-paginate="suite in testsuitlist | itemsPerPage: 10">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;">
+ <div>
+ <a style="color:#e95420" ng-click="gotoDetail(suite)"> {{suite}}
+ </a>
+ </div>
+ <div>
+ <!-- <button class="btn btn-default btn-sm" ng-click="gotoDetail(suite)">Detail</button> -->
+ <button class="btn btn-default btn-sm" ng-click="openDeleteEnv(suite,'test suite')">Delete</button>
+ </div>
+
+ </div>
+
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+ </div>
+
+
+
+
+
+
+
+
+ </div>
+
+
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+<style>
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+
+ .form-control {
+ border-radius: 5px;
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 19px;
+ height: 19px;
+ opacity: 0.8;
+ margin-left: 5px;
+ margin-top: 4px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/app/views/suitedetail.html b/gui/app/views/suitedetail.html
new file mode 100644
index 000000000..6122f6560
--- /dev/null
+++ b/gui/app/views/suitedetail.html
@@ -0,0 +1,110 @@
+<div class="content">
+ <!--testcaselist-->
+ <div>
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+
+ <h3>Detail</h3>
+ <hr/>
+
+ <textarea ng-model="suiteinfo" spellcheck="false">
+
+ </textarea>
+
+
+
+
+
+
+
+ </div>
+
+
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 19px;
+ height: 19px;
+ opacity: 0.8;
+ margin-left: 5px;
+ margin-top: 4px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/app/views/taskList.html b/gui/app/views/taskList.html
new file mode 100644
index 000000000..159fed5c9
--- /dev/null
+++ b/gui/app/views/taskList.html
@@ -0,0 +1,62 @@
+<div class="content">
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+ <h3>Detail</h3>
+ <hr/>
+ <div style="display:flex;flex-direction:row">
+ <div>
+ <h4>{{taskDetailData.name}}</h4>
+ <div style="margin-top:5px;">{{taskDetailData.time}}</div>
+ </div>
+ <div class="progree-parent" ng-show="taskDetailData.status!=2" style="margin-top:34px;margin-left:30px;">
+ <div class="progree-child" ng-style="{'width':taskDetailData.stausWidth}">
+ </div>
+
+ </div>
+ <div class="progree-parent" ng-show="taskDetailData.status==2" style="background-color:red;margin-top:34px;margin-left:30px;">
+ <div class="progree-child" style="width:0">
+ </div>
+ </div>
+ <i class="fa fa-check" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: #2ecc71;" ng-show="taskDetailData.status==1">finish</i>
+ <i class="fa fa-spinner" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: #2ecc71;" ng-show="taskDetailData.status==0">runing</i>
+ <i class="fa fa-exclamation-triangle" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: red;" ng-show="taskDetailData.status==2">failed</i>
+ </div>
+
+ <div style="margin-top:5px;">Environment : {{displayEnv.name}} </div>
+ <div ng-show="taskDetailData.case_name!=false" style="margin-top:5px;margin-bottom:5px;"> Name : {{taskDetailData.case_name}}</div>
+ <textarea ng-model="taskDetailData.content" spellcheck="false">
+
+ </textarea>
+
+ <div style="text-align:center;margin-top:20px;">
+ <button class="btn btn-default" ng-click="createTask(name)" ng-show="">Run</button>
+ </div>
+</div>
+
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ }
+
+ select {
+ height: 30px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ width: 135px;
+ margin-top: 20px;
+ margin-left: 20px;
+ }
+
+ textarea {
+ width: 100%;
+ height: 350px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ }
+
+ .content {
+ height: 90%;
+ }
+</style>
diff --git a/gui/app/views/taskmodify.html b/gui/app/views/taskmodify.html
new file mode 100644
index 000000000..a4593f745
--- /dev/null
+++ b/gui/app/views/taskmodify.html
@@ -0,0 +1,162 @@
+<div class="content">
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+ <h4>Modify </h4>
+
+ <hr/>
+
+ <div>
+ <div style="display:inline">Name <input type="text" ng-model="taskDetailData.name" style="width:200px" /></div>
+
+ <button class="btn btn-default" ng-click="runAtask()" style="float:right;margin-right:10px;">Run</button>
+ </div>
+ <hr/>
+
+ <div bs-tabs>
+ <div data-title="Environment" bs-pane>
+ <div style="margin-top:10px">
+ <div style="display:inline">Choose Environment : {{envName}}</div>
+ <button class="btn btn-default" style="display:inline;float:right;margin-right:10px;margin-top: -4px;" ng-click="addEnvToTask()">Confirm</button>
+ </div>
+ <hr />
+ <div dir-paginate="env in environmentList | orderBy:'-id' | itemsPerPage: 10 ">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;" ng-class="{deepColor: $index%2==0}">
+ <div> {{env.name}}</div>
+ <!--<button class="btn btn-default btn-sm" ng-click="gotoDetail('false',env.uuid)">detail</button>-->
+ <img src="images/checkyes.png" style="height:18px;cursor:pointer" ng-click="constructTestSuit(env.uuid,env.name)" ng-show="selectEnv==env.uuid" />
+ <img src="images/checkno.png" style="height:18px;cursor:pointer" ng-click="constructTestSuit(env.uuid,env.name)" ng-show="selectEnv!=env.uuid" />
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+
+ </div>
+ <div data-title="Content" bs-pane>
+ <div style="margin-top:10px;">
+ <button class="btn btn-default" ng-click="changeStatussourceFalse()">Modify Content</button>
+ <button class="btn btn-default" ng-click="changeStatussourceTrue()">Modify Source</button>
+ <div class="label-type" ng-show="taskDetailData.suite==false"> Test Case</div>
+ <div class="label-type" ng-show="taskDetailData.suite==true"> Test Suite</div>
+ <button class="btn btn-default" style="float:right" ng-disabled="sourceShow==null" ng-click="confirmToServer(contentInfo,taskDetailData.content)">Confirm</button>
+ </div>
+
+
+ <textarea ng-model="taskDetailData.content" ng-show="sourceShow==false" style="margin-top:5px;" spellcheck="false">
+
+
+ </textarea>
+
+ <div ng-show="sourceShow==true">
+ <div style="display:flex;flex-direction:row">
+ <div style="margin-top:20px;">Source of Content</div>
+
+
+ <select ng-model="selectType" ng-change="triggerContent(selectType)" data-ng-options="blisterPackTemplate as blisterPackTemplate.name for blisterPackTemplate in blisterPackTemplates">
+ <option value="">Choose...</option>
+ </select>
+
+ </div>
+
+ <div style="margin-top:10px" ng-show="selectCase!=null ">
+ <div style="display:inline">Choose Source : {{selectCase}}</div>
+ <!--<button class="btn btn-default" style="display:inline;float:right;margin-right:10px;margin-top: -4px;" ng-click="confirmAddCaseOrSuite(contentInfo)">Confirm</button>-->
+ <button class="btn btn-default" style="display:inline;float:right;margin-right:10px;margin-top: -4px;" ng-click="getTestDeatil()">Edit</button>
+ </div>
+ <hr/>
+
+ <div ng-show="displayTable==true">
+ <div ng-show="testcaselist.testcases.length!=0 && selectType.name=='Test Case'">
+ <div dir-paginate="test in testcaselist.testcases | itemsPerPage: 10" pagination-id="testcase">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;" ng-class="{deepColor: $index%2==0}">
+ <div> {{test.Name}}</div>
+ <div style="font-size:10px;">{{test.Description}}</div>
+ <img src="images/checkyes.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(test.Name)" ng-show="selectCase==test.Name" />
+ <img src="images/checkno.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(test.Name)" ng-show="selectCase!=test.Name" />
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls pagination-id="testcase"></dir-pagination-controls>
+ </center>
+ </div>
+
+ <div ng-show="testsuitlist.length!=0 && selectType.name=='Test Suite'">
+ <div dir-paginate="suite in testsuitlist | itemsPerPage: 10" pagination-id="testsuite">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;" ng-class="{deepColor: $index%2==0}">
+ <div> {{suite}}</div>
+
+ <img src="images/checkyes.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(suite)" ng-show="selectCase==suite" />
+ <img src="images/checkno.png" style="height:18px;cursor:pointer" ng-click="constructTestCase(suite)" ng-show="selectCase!=suite" />
+
+ </div>
+ <!--<hr style="margin-top:5px;margin-bottom:5px;" />-->
+ </div>
+ <center>
+ <dir-pagination-controls pagination-id="testsuite"></dir-pagination-controls>
+ </center>
+ </div>
+ </div>
+
+ <div ng-show="displayTable==false">
+ <textarea ng-model="contentInfo" spellcheck="false">
+ </textarea>
+
+
+ </div>
+ </div>
+
+
+
+
+ </div>
+ </div>
+
+
+</div>
+<toaster-container></toaster-container>
+
+
+<style>
+ input {
+ border-radius: 10px;
+ border: 1px solid #eeeeee;
+ width: 100%;
+ padding: 5px;
+ }
+
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+
+ select {
+ height: 30px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ width: 135px;
+ margin-top: 20px;
+ margin-left: 20px;
+ }
+
+ textarea {
+ width: 100%;
+ height: 350px;
+ border-radius: 5px;
+ border: 1px solid #e8e8e8;
+ }
+
+ .label-type {
+ display: inline;
+ background-color: #2ecc71;
+ color: #fff;
+ border-radius: 5px;
+ padding: 3px;
+ font-size: 10px;
+ }
+
+ .content {
+ height: auto;
+ }
+</style>
diff --git a/gui/app/views/testcasechoose.html b/gui/app/views/testcasechoose.html
new file mode 100644
index 000000000..12bdb834f
--- /dev/null
+++ b/gui/app/views/testcasechoose.html
@@ -0,0 +1,48 @@
+<div class="content">
+
+ <div>
+ Test case list
+ <button class="btn btn-default" style="margin-left:20px;" ng-click="openDialog()">
+ <div ng-show="!loadingOPENrc">Create </div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="loadingOPENrc" />
+ </button>
+
+
+ <hr/> You have choose :
+ <div ng-repeat="selected in suitReconstructList" style="display:inline;" class="item">{{selected}}</div>
+ <hr/>
+
+ <!--<div ng-repeat="env in environmentList">
+ {{env.name}}
+ </div>-->
+ <div dir-paginate="test in testcaselist.testcases | itemsPerPage: 10">
+ <div style="display:flex;flex-direction:row;">
+ <img src="images/checkyes.png" style="height:12px;cursor:pointer" ng-click="constructTestSuit(test.Name)" ng-show="testsuiteList.indexOf(test.Name)>-1" />
+ <img src="images/checkno.png" style="height:12px;cursor:pointer" ng-click="constructTestSuit(test.Name)" ng-show="testsuiteList.indexOf(test.Name)==-1" />
+ <div style="margin-left:50px;"> {{test.Name}}</div>
+ <div style="font-size:10px;margin-left:100px">{{test.Description}}</div>
+
+ </div>
+ <hr style="margin-top:5px;margin-bottom:5px;" />
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+
+
+
+ </div>
+ <toaster-container></toaster-container>
+
+ <style>
+ .item {
+ background-color: #3498db;
+ color: #fff;
+ width: 150px;
+ border-radius: 5px;
+ padding-left: 10px;
+ margin-left: 2px;
+ margin-top: 3px;
+ padding: 4px;
+ }
+ </style>
diff --git a/gui/app/views/testcasedetail.html b/gui/app/views/testcasedetail.html
new file mode 100644
index 000000000..43a51537f
--- /dev/null
+++ b/gui/app/views/testcasedetail.html
@@ -0,0 +1,110 @@
+<div class="content">
+ <!--testcaselist-->
+ <div>
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+
+ <h4>Detail</h4>
+ <hr/>
+
+ <textarea ng-model="testcaseInfo" spellcheck="false">
+
+ </textarea>
+
+
+
+
+
+
+
+ </div>
+
+
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 19px;
+ height: 19px;
+ opacity: 0.8;
+ margin-left: 5px;
+ margin-top: 4px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/app/views/testcaselist.html b/gui/app/views/testcaselist.html
new file mode 100644
index 000000000..3e8cfccf9
--- /dev/null
+++ b/gui/app/views/testcaselist.html
@@ -0,0 +1,150 @@
+<div class="content">
+ <!--testcaselist-->
+ <i class="fa fa-arrow-left fa-1x" aria-hidden="true" style="color: #999;cursor:pointer" ng-click="goBack()">Back</i>
+
+ <div>
+ Test Cases
+ <button class="btn btn-default" style="margin-left:20px;" ngf-select="uploadFiles($file, $invalidFiles)" ngf-max-size="5MB">
+ <div ng-show="!loadingOPENrc">Upload</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="loadingOPENrc" />
+ </button>
+
+ <!--<div ng-show="displayOpenrcFile!=null || displayOpenrcFile!=undefined">
+ {{displayOpenrcFile.name}} last modified: {{filelastModified}}
+ </div>-->
+ <hr/>
+
+ <!--<div ng-repeat="env in environmentList">
+ {{env.name}}
+ </div>-->
+ <div dw-loading="key" dw-loading-options="{text:'loading'}">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;background-color: #f9f9f9">
+ <div style="font-weight:600">Name</div>
+ <div style="font-weight:600;margin-right:4px;">Operate</div>
+
+ </div>
+
+ <div dir-paginate="test in testcaselist.testcases | itemsPerPage: 10">
+ <div style="display:flex;flex-direction:row;justify-content:space-between;padding:8px;border-top: 1px solid #e9ecec;">
+ <div>
+
+ <a style="color:#e95420" ng-click="gotoDetail(test.Name)">
+ {{test.Name}}
+ </a>
+ </div>
+ <div style="font-size:10px;">{{test.Description}}</div>
+ <div>
+ <!-- <button class="btn btn-default btn-sm" ng-click="gotoDetail(test.Name)">Detail</button> -->
+ <button class="btn btn-default btn-sm" ng-click="openDeleteEnv(test.Name,'test case')">Delete</button>
+ </div>
+
+ </div>
+
+ </div>
+ <center>
+ <dir-pagination-controls></dir-pagination-controls>
+ </center>
+ </div>
+
+
+
+
+
+
+
+ </div>
+
+
+
+
+</div>
+
+<toaster-container></toaster-container>
+
+<style>
+ .deepColor {
+ background-color: #f9f9f9;
+ }
+
+ .form-control {
+ border-radius: 5px;
+ width: 300px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 19px;
+ height: 19px;
+ opacity: 0.8;
+ margin-left: 5px;
+ margin-top: 4px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/app/views/uploadImage.html b/gui/app/views/uploadImage.html
new file mode 100644
index 000000000..17ccfdb8b
--- /dev/null
+++ b/gui/app/views/uploadImage.html
@@ -0,0 +1,145 @@
+<!--upload image page-->
+
+<div class="content">
+ <div style="display:flex;flex-direction:row;">
+ <div style="width:750px;">
+
+ <h3>{{baseElementInfo.name}} -- Image
+ <button class="btn btn-default" style="float:right" ng-click="goNext()">Next</button>
+ </h3>
+ <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
+
+ <hr/>
+ <button class="btn btn-default" ng-click="uploadImage()">
+ <div ng-if="!showloading">Load Image</div>
+ <img src="images/loading2.gif" width="25" height="25" ng-if="showloading" />
+ </button>
+ <i class="fa fa-check" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: #2ecc71;" ng-show="imageStatus==1&&ifshowStatus==1">done</i>
+ <i class="fa fa-spinner" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: #2ecc71;" ng-show="imageStatus==0&&ifshowStatus==1">loading</i>
+ <i class="fa fa-exclamation-triangle" aria-hidden="true" style="margin-top:34px;margin-left:5px;color: red;" ng-show="imageStatus==2&&ifshowStatus==1">error</i>
+
+ <hr>
+ <h4>Current Images</h4>
+
+ <div>
+ <table class="table table-striped">
+
+ <tr>
+ <th>name</th>
+ <th>size</th>
+ <th>status</th>
+ <th>time</th>
+ </tr>
+ <tr ng-repeat="image in imageListData">
+ <td>{{image.name}}</td>
+ <td>{{image.size/1024}} MB</td>
+ <td>{{image.status}}</td>
+ <td>{{image.time}}</td>
+
+ </tr>
+
+
+
+ </table>
+ </div>
+
+
+
+
+
+
+
+
+
+ </div>
+
+
+ </div>
+
+</div>
+<toaster-container></toaster-container>
+
+<style>
+ .form-control {
+ border-radius: 5px;
+ width: 200px;
+ margin-bottom: 10px;
+ }
+
+ .uploadbutton {
+ background-color: #007ACC;
+ color: #fff;
+ border: 0px;
+ border-radius: 5px;
+ height: 27px;
+ }
+
+ .edit-title {
+ border: 0px;
+ background-color: #ffffff;
+ margin-bottom: 5px;
+ font-size: 12px;
+ }
+
+ .null-edit-title {
+ border: 1px solid #e5e6e7;
+ border-radius: 5px;
+ margin-bottom: 3px;
+ }
+
+ .item-info {
+ display: flex;
+ flex-direction: row;
+ }
+
+ .delete-img {
+ width: 15px;
+ height: 15px;
+ opacity: 0.8;
+ margin-left: -10px;
+ margin-top: -3px;
+ cursor: pointer;
+ }
+
+ .nextButton {
+ margin-top: 30px;
+ border: none;
+ border-radius: 5px;
+ padding: 6px;
+ background-color: #339933;
+ color: #ffffff;
+ text-align: center;
+ /* margin-left: 300px; */
+ }
+
+ .bs-sidenav {
+ margin-top: 40px;
+ margin-bottom: 20px;
+ width: 124px;
+ }
+
+ .nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+ }
+
+ .nav>li {
+ position: relative;
+ display: block;
+ }
+
+ li {
+ display: list-item;
+ text-align: -webkit-match-parent;
+ }
+
+ a {
+ cursor: pointer;
+ }
+
+ a.active {
+ background-color: #EEEEEE;
+ border-radius: 5px;
+ }
+</style>
diff --git a/gui/bower.json b/gui/bower.json
new file mode 100644
index 000000000..6da3bee3c
--- /dev/null
+++ b/gui/bower.json
@@ -0,0 +1,45 @@
+{
+ "name": "yard-stick-gui2",
+ "version": "0.0.0",
+ "dependencies": {
+ "angular": "^1.4.0",
+ "bootstrap": "^3.2.0",
+ "angular-strap": "^2.3.12",
+ "angular-ui-router": "^1.0.3",
+ "angular-animate": "^1.6.4",
+ "angular-breadcrumb": "^0.5.0",
+ "angular-wizard": "^0.10.0",
+ "angular-resource": "^1.6.4",
+ "ng-file-upload": "^12.2.13",
+ "AngularJS-Toaster": "angularjs-toaster#^2.1.0",
+ "ng-dialog": "^1.3.0",
+ "angularUtils-pagination": "angular-utils-pagination#^0.11.1",
+ "components-font-awesome": "^4.7.0",
+ "ngstorage": "^0.3.11",
+ "v-accordion": "^1.6.0",
+ "angular-loading": "^0.1.4",
+ "angular-bootstrap": "^2.5.0",
+ "angular-sanitize": "^1.6.5"
+ },
+ "devDependencies": {
+ "angular-mocks": "^1.4.0"
+ },
+ "appPath": "app",
+ "moduleName": "yardStickGui2App",
+ "overrides": {
+ "bootstrap": {
+ "main": [
+ "less/bootstrap.less",
+ "dist/css/bootstrap.css",
+ "dist/js/bootstrap.js"
+ ]
+ },
+ "angular-loading": {
+ "main": [
+ "angular-loading.css",
+ "angular-loading.js",
+ "../spin.js/spin.js"
+ ]
+ }
+ }
+}
diff --git a/gui/gui.sh b/gui/gui.sh
new file mode 100755
index 000000000..12a14923e
--- /dev/null
+++ b/gui/gui.sh
@@ -0,0 +1,8 @@
+apt-get install -y nodejs
+apt-get install -y npm
+ln -s /usr/bin/nodejs /usr/bin/node
+npm install
+npm install -g grunt
+npm install -g bower
+bower install --force --allow-root
+grunt build
diff --git a/gui/package.json b/gui/package.json
new file mode 100644
index 000000000..b85c75469
--- /dev/null
+++ b/gui/package.json
@@ -0,0 +1,43 @@
+{
+ "name": "yardstickgui2",
+ "private": true,
+ "devDependencies": {
+ "autoprefixer-core": "^5.2.1",
+ "grunt": "^0.4.5",
+ "grunt-angular-templates": "^0.5.7",
+ "grunt-concurrent": "^1.0.0",
+ "grunt-contrib-clean": "^0.6.0",
+ "grunt-contrib-concat": "^0.5.0",
+ "grunt-contrib-connect": "^0.9.0",
+ "grunt-contrib-copy": "^0.7.0",
+ "grunt-contrib-cssmin": "^0.12.0",
+ "grunt-contrib-htmlmin": "^0.4.0",
+ "grunt-contrib-imagemin": "^1.0.0",
+ "grunt-contrib-jshint": "^0.11.0",
+ "grunt-contrib-uglify": "^0.7.0",
+ "grunt-contrib-watch": "^0.6.1",
+ "grunt-filerev": "^2.1.2",
+ "grunt-google-cdn": "^0.4.3",
+ "grunt-jscs": "^1.8.0",
+ "grunt-newer": "^1.1.0",
+ "grunt-ng-annotate": "^0.9.2",
+ "grunt-postcss": "^0.5.5",
+ "grunt-svgmin": "^2.0.0",
+ "grunt-usemin": "^3.0.0",
+ "grunt-wiredep": "^2.0.0",
+ "jasmine-core": "^2.6.2",
+ "jit-grunt": "^0.9.1",
+ "jshint-stylish": "^1.0.0",
+ "karma": "^1.7.0",
+ "karma-jasmine": "^1.1.0",
+ "karma-phantomjs-launcher": "^1.0.4",
+ "phantomjs-prebuilt": "^2.1.14",
+ "time-grunt": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "scripts": {
+ "test": "karma start test\\karma.conf.js"
+ }
+}
diff --git a/gui/test/.jshintrc b/gui/test/.jshintrc
new file mode 100644
index 000000000..b2ce4eff4
--- /dev/null
+++ b/gui/test/.jshintrc
@@ -0,0 +1,18 @@
+{
+ "bitwise": true,
+ "browser": true,
+ "curly": true,
+ "eqeqeq": true,
+ "esnext": true,
+ "jasmine": true,
+ "latedef": true,
+ "noarg": true,
+ "node": true,
+ "strict": true,
+ "undef": true,
+ "unused": true,
+ "globals": {
+ "angular": false,
+ "inject": false
+ }
+}
diff --git a/gui/test/karma.conf.js b/gui/test/karma.conf.js
new file mode 100644
index 000000000..a9ab3a824
--- /dev/null
+++ b/gui/test/karma.conf.js
@@ -0,0 +1,93 @@
+// Karma configuration
+// Generated on 2017-05-31
+
+module.exports = function(config) {
+ 'use strict';
+
+ config.set({
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: true,
+
+ // base path, that will be used to resolve files and exclude
+ basePath: '../',
+
+ // testing framework to use (jasmine/mocha/qunit/...)
+ // as well as any additional frameworks (requirejs/chai/sinon/...)
+ frameworks: [
+ 'jasmine'
+ ],
+
+ // list of files / patterns to load in the browser
+ files: [
+ // bower:js
+ 'bower_components/jquery/dist/jquery.js',
+ 'bower_components/angular/angular.js',
+ 'bower_components/bootstrap/dist/js/bootstrap.js',
+ 'bower_components/angular-strap/dist/angular-strap.js',
+ 'bower_components/angular-strap/dist/angular-strap.tpl.js',
+ 'bower_components/angular-ui-router/release/angular-ui-router.js',
+ 'bower_components/angular-animate/angular-animate.js',
+ 'bower_components/angular-breadcrumb/release/angular-breadcrumb.js',
+ 'bower_components/angular-wizard/dist/angular-wizard.min.js',
+ 'bower_components/angular-resource/angular-resource.js',
+ 'bower_components/ng-file-upload/ng-file-upload.js',
+ 'bower_components/AngularJS-Toaster/toaster.js',
+ 'bower_components/ng-dialog/js/ngDialog.js',
+ 'bower_components/angularUtils-pagination/dirPagination.js',
+ 'bower_components/ngstorage/ngStorage.js',
+ 'bower_components/v-accordion/dist/v-accordion.js',
+ 'bower_components/spin.js/spin.js',
+ 'bower_components/angular-loading/angular-loading.js',
+ 'bower_components/spin.js/spin.js',
+ 'bower_components/angular-bootstrap/ui-bootstrap-tpls.js',
+ 'bower_components/angular-sanitize/angular-sanitize.js',
+ 'bower_components/angular-mocks/angular-mocks.js',
+ // endbower
+ 'app/scripts/**/*.js',
+ 'test/mock/**/*.js',
+ 'test/spec/**/*.js'
+ ],
+
+ // list of files / patterns to exclude
+ exclude: [
+ ],
+
+ // web server port
+ port: 8080,
+
+ // Start these browsers, currently available:
+ // - Chrome
+ // - ChromeCanary
+ // - Firefox
+ // - Opera
+ // - Safari (only Mac)
+ // - PhantomJS
+ // - IE (only Windows)
+ browsers: [
+ 'PhantomJS'
+ ],
+
+ // Which plugins to enable
+ plugins: [
+ 'karma-phantomjs-launcher',
+ 'karma-jasmine'
+ ],
+
+ // Continuous Integration mode
+ // if true, it capture browsers, run tests and exit
+ singleRun: false,
+
+ colors: true,
+
+ // level of logging
+ // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+ // Uncomment the following lines if you are using grunt's server to run the tests
+ // proxies: {
+ // '/': 'http://localhost:9000/'
+ // },
+ // URL root prevent conflicts with the site root
+ // urlRoot: '_karma_'
+ });
+};
diff --git a/gui/test/spec/controllers/main.js b/gui/test/spec/controllers/main.js
new file mode 100644
index 000000000..27e0a5ad3
--- /dev/null
+++ b/gui/test/spec/controllers/main.js
@@ -0,0 +1,23 @@
+'use strict';
+
+describe('Controller: MainCtrl', function () {
+
+ // load the controller's module
+ beforeEach(module('yardStickGui2App'));
+
+ var MainCtrl,
+ scope;
+
+ // Initialize the controller and a mock scope
+ beforeEach(inject(function ($controller, $rootScope) {
+ scope = $rootScope.$new();
+ MainCtrl = $controller('MainCtrl', {
+ $scope: scope
+ // place here mocked dependencies
+ });
+ }));
+
+ it('should attach a list of awesomeThings to the scope', function () {
+ expect(MainCtrl.awesomeThings.length).toBe(3);
+ });
+});
diff --git a/install.sh b/install.sh
index ad14b8e0b..e82ae0233 100755
--- a/install.sh
+++ b/install.sh
@@ -86,7 +86,10 @@ easy_install -U pip
pip install -r requirements.txt
pip install -e .
-/bin/bash "$(pwd)/api/api-prepare.sh"
+/bin/bash "${PWD}/docker/uwsgi.sh"
+/bin/bash "${PWD}/docker/nginx.sh"
+cd "${PWD}/gui" && /bin/bash gui.sh
+mv dist /etc/nginx/yardstick/gui
service nginx restart
uwsgi -i /etc/yardstick/yardstick.ini