[TIC-Web] Update The Flow For The Image Creation. 08/116408/6
authorHee Kyoung, Oh <heekyoung.oh@samsung.com>
Fri, 24 Feb 2017 07:22:15 +0000 (16:22 +0900)
committerChangHyun Lee <leechwin.lee@samsung.com>
Mon, 27 Feb 2017 07:16:19 +0000 (16:16 +0900)
- Change the process of creation
- Using Database
- When creation tic_job table updated
- When creation tic_image table updated
- Can show the log for the each job
- Update the config.json
- Delete the socketevent.js, it was duplicated meaning that config.json
- Delete the filesystem.js, cause using database
- MIC writes the logfile that mic.log

Change-Id: Ibac100bf7f9248c8e3f7adf828ae8fa54e86e6e2
Signed-off-by: Hee Kyoung, Oh <heekyoung.oh@samsung.com>
23 files changed:
config.json
controller/filesystem.js [deleted file]
controller/mariadb.js
controller/mic.js
controller/router.js
controller/server.js
controller/socketevent.js [deleted file]
controller/socketio.js
controller/ticcore.js [new file with mode: 0644]
package.json
public/src/css/style.css
public/src/index.html
public/src/js/main.js
public/src/js/model/ImageModel.js [new file with mode: 0644]
public/src/js/model/JobModel.js
public/src/js/page/image.js
public/src/js/page/job.js
public/src/js/page/package.js
public/src/js/widget/ImageEmptyItem.js [new file with mode: 0644]
public/src/js/widget/ImageItem.js [new file with mode: 0644]
public/src/js/widget/JobLog.js [new file with mode: 0644]
public/src/js/widget/JobTableEmptyItem.js
public/src/js/widget/JobTableItem.js

index 4a65490..690b595 100644 (file)
@@ -2,17 +2,47 @@
     "TIC_WEB": {
         "PORT" : 8081,
         "PATH": "/var/tmp/tic-web/",
+        "PATH_ABSTRACT": "/tic/",
         "LOG_FILE" : "/var/tmp/tic-web/tic-web.log",
-        "KS_OUT_DIR" : "/var/tmp/tic-web/ks/"
-    },
-    "DATABASE": {
-        "GET_ALL_COUNT": "/api/image/count",
-        "GET_ALL_LISTITEM": "/api/image/list"
+        "KS_FILE_NAME": "default.ks",
+        "LOG_FILE_NAME": "mic.log",
+        "IMAGE_FILE_NAME": "image.tar.gz"
     },
     "TIC_CORE": {
         "PORT" : 8082
     },
     "MIC" : {
         "OUT_DIR" : "/var/tmp/tic-web/images/"
+    },
+    "EVENT": {
+        "SOCKET":{
+            "APP_CONFIG_TO": "ws/app/config/to",
+            "APP_CONFIG_FROM": "ws/app/config/from",
+            "FS_IMAGE_ADD_FROM": "ws/fs/image/add/from",
+            "FS_IMAGE_ADD_TO": "ws/fs/image/add/to",
+            "FS_IMAGE_ADD_FINISH": "ws/fs/image/add/finish",
+            "FS_IMAGE_ADD_FAIL": "ws/fs/image/add/fail",
+            "FS_IMAGE_ADD_KILL": "ws/fs/image/add/kill",
+            "MIC_AVAILABLE_FROM": "ws/mic/available/from",
+            "MIC_AVAILABLE_TO": "ws/mic/available/to"
+        },
+        "JOB": {
+            "JOB_GET_ALL_COUNT": "/api/job/count",
+            "JOB_GET_ALL_LISTITEM": "/api/job/list",
+            "JOB_GET_BYID": "/api/job/",
+            "JOB_ADD_ONE": "/api/job/add/",
+            "JOB_EDIT_ONE": "/api/job/edit/"
+        },
+        "PACKAGE": {
+            "TEST": "testtest"
+        },
+        "IMAGE": {
+            "IMAGE_GET_ALL_COUNT": "/api/image/count/",
+            "IMAGE_GET_ALL_LISTITEM": "/api/image/list/",
+            "IMAGE_ADD_ONE": "/api/image/add/"
+        },
+        "SESSION": {
+            "TEST": "testtest"
+        }
     }
 }
\ No newline at end of file
diff --git a/controller/filesystem.js b/controller/filesystem.js
deleted file mode 100644 (file)
index fe5233c..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-'use strict';
-
-var fs = require('fs');
-var mime = require('mime');
-var path = require('path');
-var mkdirp = require('mkdirp');
-var appConfig = require('../config.json');
-
-var JL = require('jsnlog').JL;
-
-var logger = JL('filesystem.js');
-
-var filesystem = filesystem || {};
-
-filesystem.init = function () {
-
-    function fnMkdir(paramPath) {
-        mkdirp(paramPath, function (err) {
-            if (err) {
-                logger.error(err);
-            } else {
-                logger.info(paramPath + ' exists');
-            }
-        });
-    }
-
-    fnMkdir(appConfig.TIC_WEB.KS_OUT_DIR);
-    fnMkdir(appConfig.MIC.OUT_DIR);
-};
-
-filesystem.list = function (dirPath) {
-    var results, info, list;
-
-    results = [];
-
-    list = fs.readdirSync(dirPath);
-    list.forEach(function(file) {
-        var fileStat, filePath;
-
-        filePath = dirPath + file;
-
-        fileStat = fs.statSync(filePath);
-
-        if (fileStat && fileStat.isDirectory()) {
-            results = results.concat(filesystem.list(filePath))
-        } else {
-            info = {
-                name: file,
-                size: fileStat['size'],
-                atime: fileStat['atime'],
-                mtime: fileStat['mtime'],
-                ctime: fileStat['ctime'],
-                birthtime: fileStat['birthtime']
-            }
-            results.push(info);
-        }
-    });
-    return results;
-};
-
-filesystem.download = function (req, res) {
-    var fileName, filePath, fileMimetype, fileStream;
-
-    fileName = req.params.filename;
-    filePath = appConfig.MIC.OUT_DIR + fileName;
-    fileMimetype = mime.lookup(filePath);
-
-    res.setHeader('Content-disposition', 'attachment; filename=' + fileName);
-    res.setHeader('Content-type', fileMimetype);
-
-    fileStream = fs.createReadStream(filePath);
-    fileStream.pipe(res);
-};
-
-filesystem.remove = function () {
-    logger.info('filesystem.remove called');
-};
-
-module.exports = filesystem;
index 18f1922..1340383 100644 (file)
@@ -3,6 +3,7 @@
 var mariaSql = require('mariasql');
 var JL = require('jsnlog').JL;
 var logger = JL('mariadb.js');
+var _ = require('lodash');
 
 /**
  * Client
@@ -14,90 +15,353 @@ var mariaSqlClient;
  */
 var mariadb = mariadb || {};
 
-mariadb.getTotalCount = function getTotalCount(req, res) {
-    logger.info('getTotalCount');
-    
+mariadb.queries = {
+    'addJob': [
+        'insert into tic_job ',
+        '(job_status, job_deleted, job_hasksfile, job_updater, job_uptime, job_register, job_regtime) ',
+        'values ("READY", false, false, "tic", now(), "tic", now());'
+    ],
+    'getJobById': [
+        'select tic_job.job_id job_id, ',
+            'tic_job.job_status job_status, ',
+            'tic_job.job_image_id job_image_id, ',
+            'tic_image.image_name job_image_name, ',
+            'tic_image.image_size job_image_size, ',
+            'tic_job.job_hasksfile job_hasksfile, ',
+            'tic_job.job_uptime job_uptime ',
+        'from tic_job ',
+        'left join tic_image on tic_job.job_image_id = tic_image.image_id ',
+        'where tic_job.job_deleted = false ',
+        'and job_id = <%= strJobId %>;'
+    ],
+    'getJobsTotalCount': [
+        'select count(job_id) as total_count ',
+        'from tic_job ',
+        'where job_deleted = false;'
+    ],
+    'getJobsAllList': [
+        'select tic_job.job_id job_id, ',
+            'tic_job.job_status job_status, ',
+            'tic_job.job_image_id job_image_id, ',
+            'tic_image.image_name job_image_name, ',
+            'tic_image.image_size job_image_size, ',
+            'tic_job.job_hasksfile job_hasksfile, ',
+            'tic_job.job_uptime job_uptime ',
+        'from tic_job ',
+        'left join tic_image on tic_job.job_image_id = tic_image.image_id ',
+        'where tic_job.job_deleted = false ',
+        'order by job_id desc ',
+        'limit <%= startNum %> , 10;'
+    ],
+    'getImagesAllList': [
+        'select tic_job.job_image_id image_id, ',
+        'tic_job.job_id image_job_id, ',
+        'tic_image.image_name image_name, ',
+        'tic_image.image_size image_size, ',
+        'tic_job.job_hasksfile image_hasksfile, ',
+        'tic_job.job_status image_status, ',
+        'tic_job.job_uptime image_uptime ',
+        'from tic_job inner join tic_image ',
+        'where tic_job.job_image_id = tic_image.image_id ',
+        'and tic_job.job_deleted = false ',
+        'order by tic_job.job_id desc ',
+        'limit <%= startNum %> , 10;'
+    ],
+    'getImagesTotalCount': [
+        'select count(image_id) as total_count ',
+        'from tic_image;',
+    ],
+    'addImage': [
+        'insert into tic_image ',
+        '(',
+            'image_type, ',
+            'image_pid',
+        ') ',
+        'values (',
+            '"<%= imageType %>", ',
+            '"<%= imagePid %>"',
+        ');'
+    ]
+};
 
-    var queryString, query;
+mariadb.doQuery = function doQuery (queryString, callback) {
+    return mariaSqlClient.query(queryString, callback);
+};
 
-    // query
-    queryString = 'select count(job_id) as total_count \
-                from tic_job \
-                where job_deleted = false';
+/**
+ * JOBS
+ */
+/**
+ * Edit the Job By Id
+ */
+mariadb.editJob = function addJob (req, res) {
+    var queryString, strJobId, reqParam,
+    job_status, job_deleted, job_hasksfile, job_image_id;
 
-    query = mariaSqlClient.query(
-        queryString,
-        function (err, rows) {
-            if (err) {
-                logger.error(err);
-                throw err;
-            }
-            res.json(rows);
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
         }
-    );
+
+        logger.info('editJob.success');
+        res.json(rows);
+    }
+
+    strJobId = req.params.id;
+    reqParam = req.body;
+    job_status = reqParam.job_status;
+    job_deleted = reqParam.job_deleted;
+    job_hasksfile = reqParam.job_hasksfile;
+    job_image_id = reqParam.job_image_id;
+
+    queryString = 'update tic_job set';
+    if (job_image_id) queryString += ' job_image_id = "' + job_image_id + '",';
+    if (job_status) queryString += ' job_status = "' + job_status + '",';
+    if (job_deleted) queryString += ' job_deleted = ' + job_deleted + ',';
+    if (job_hasksfile) queryString += ' job_hasksfile = ' + job_hasksfile + ',';
+    queryString += ' job_updater = "tic",';
+    queryString += ' job_uptime = now()';
+    queryString += ' where job_id = ' + strJobId + ';';
+
+    logger.info('editJob: query = ' + queryString);
+
+    this.doQuery(queryString, onSuccess);
 };
 
-mariadb.getAllImages = function getAllImages (req, res) {
-    logger.info('getAllImages');
+/**
+ * Add The New Job
+ */
+mariadb.addJob = function addJob (req, res) {
+    var queryString;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+
+        logger.info('addJob.success: {job_id: ' + rows.info.insertId + '}');
+        res.json({
+            job_id: rows.info.insertId
+        });
+    }
+
+    queryString = _.join(this.queries['addJob'], '');
+
+    logger.info('addJob: query = ' + queryString);
 
-    var queryString, reqParam, pageNum, startNum, query;
+    // call
+    this.doQuery(queryString, onSuccess);
+};
+
+/**
+ * Get The Job By ID
+ */
+mariadb.getJobById = function getJobById (req, res) {
+    var queryString, strJobId;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+        res.json(rows);
+    }
+
+    strJobId = req.params.id;
+
+    queryString = _.template(_.join(this.queries['getJobById'], ''))({
+        strJobId: strJobId
+    });
+
+    logger.info('getJobById: query = ' + queryString);
+
+    // call
+    this.doQuery(queryString, onSuccess);
+};
+
+/**
+ * Get Total Count of Job
+ */
+mariadb.getJobsTotalCount = function getJobsTotalCount (req, res) {
+    var queryString;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+        res.json(rows);
+    }
+
+    queryString = _.join(this.queries['getJobsTotalCount'], '');
+
+    logger.info('getJobsTotalCount: query = ' + queryString);
+
+    // call
+    this.doQuery(queryString, onSuccess);
+};
+
+/**
+ * Get All Jobs
+ */
+mariadb.getJobsAllList = function getJobsAllList (req, res) {
+    var queryString, reqParam, pageNum, startNum;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+        res.json(rows);
+    }
 
     // strNum
     reqParam = req.body;
     pageNum = reqParam.pageNum;
     startNum = (pageNum - 1) * 10;
 
-    // query
-    queryString = 'select tic_job.job_id job_id, \
-                    tic_job.job_status job_status, \
-                    tic_image.image_name job_image_name, \
-                    tic_image.image_size job_image_size, \
-                    tic_job.job_uptime job_uptime \
-                from tic_job \
-                inner join tic_image on tic_job.job_image_id = tic_image.image_id \
-                where tic_job.job_deleted = false \
-                order by job_uptime desc \
-                limit ' + startNum + ', 10';
+    queryString = _.template(_.join(this.queries['getJobsAllList'], ''))({
+        startNum: startNum
+    });
+
+    logger.info('getJobsAllList: query = ' + queryString);
 
     // call
-    query = mariaSqlClient.query(
-        queryString,
-        function (err, rows) {
-            var totalCount, index;
+    this.doQuery(queryString, onSuccess);
+};
 
-            if (err) {
-                logger.error(err);
-                throw err;
-            }
 
-            totalCount = rows.info.numRows;
-            index = 1;
+/**
+ * IAMGES
+ */
 
-            for (var i in rows) {
-                rows[i]['job_index'] = index++;
-            }
+/**
+ * Get All Images
+ */
+mariadb.getImagesAllList = function getImagesAllList (req, res) {
+    var queryString, reqParam, pageNum, startNum;
 
-            res.json(rows);
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
         }
-    );
+        res.json(rows);
+    }
+
+    // strNum
+    reqParam = req.body;
+    pageNum = reqParam.pageNum;
+    startNum = (pageNum - 1) * 10;
+
+    queryString = _.template(_.join(this.queries['getImagesAllList'], ''))({
+        startNum: startNum
+    });
+
+    logger.info('getImagesAllList: query = ' + queryString);
+
+    // call
+    this.doQuery(queryString, onSuccess);
+};
+
+/**
+ * Get Total Count of Job
+ */
+mariadb.getImagesTotalCount = function getImagesTotalCount (req, res) {
+    var queryString;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+        res.json(rows);
+    }
+
+    queryString = _.join(this.queries['getImagesTotalCount'], '');
+
+    logger.info('getImagesTotalCount: query = ' + queryString);
+
+    // call
+    this.doQuery(queryString, onSuccess);
 };
 
-mariadb.addImage = function addImage () {
-    logger.info('getAllImages');
-
-    var strQuery, query;
-    
-    strQuery = 'insert into tic_job (job_updater, job_uptime, job_register, job_regtime) ';
-    strQuery =+ 'values (?, NOW(), ?, NOW())';
-    query = db.query(strQuery, ['', '', ''], function (error, result) {
-        /**
-         * TODO
-         * 
-         */
+/**
+ * Add The New Image
+ */
+mariadb.addImage = function addImage (req, res) {
+    var queryString, paramObj, imagePid;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+
+        logger.info('addJob: result = {image_id: ' + rows.info.insertId + '}');
+        res.json({
+            image_id: rows.info.insertId
+        });
+    }
+
+    paramObj = req.body;
+    imagePid = paramObj.imagePid;
+
+    queryString = _.template(_.join(this.queries['addImage'], ''))({
+        imageType: 'external',
+        imagePid: imagePid
     });
 
+    logger.info('addJob: query = ' + queryString);
+
+    // call
+    this.doQuery(queryString, onSuccess);
+};
+
+
+mariadb.editImage = function editImage (req, res) {
+    var queryString, strJobId, reqParam,
+    job_status, job_deleted, job_hasksfile, job_image_id;
+
+    function onSuccess (err, rows) {
+        if (err) {
+            logger.error(err);
+            throw err;
+        }
+
+        logger.info('editJob.success');
+        res.json(rows);
+    }
+
+    strJobId = req.params.id;
+    reqParam = req.body;
+    job_status = reqParam.job_status;
+    job_deleted = reqParam.job_deleted;
+    job_hasksfile = reqParam.job_hasksfile;
+    job_image_id = reqParam.job_image_id;
+
+    queryString = 'update tic_job set';
+    if (job_image_id) queryString += ' job_image_id = "' + job_image_id + '",';
+    if (job_status) queryString += ' job_status = "' + job_status + '",';
+    if (job_deleted) queryString += ' job_deleted = ' + job_deleted + ',';
+    if (job_hasksfile) queryString += ' job_hasksfile = ' + job_hasksfile + ',';
+    queryString += ' job_updater = "tic",';
+    queryString += ' job_uptime = now()';
+    queryString += ' where job_id = ' + strJobId + ';';
+
+    logger.info('editJob: query = ' + queryString);
+
+    this.doQuery(queryString, onSuccess);
 };
 
+/**
+ * DB
+ */
+/**
+ * Connect
+ */
 mariadb.connectToClient = function connectToClient (){
     return new Promise(function (resolve, reject) {
         // connect
@@ -112,6 +376,9 @@ mariadb.connectToClient = function connectToClient (){
     });
 };
 
+/**
+ * Create the Client
+ */
 mariadb.createClient = function createClient () {
     return new Promise(function (resolve, reject) {
         logger.info('create client');
@@ -134,6 +401,9 @@ mariadb.createClient = function createClient () {
     });
 };
 
+/**
+ * Initialize
+ */
 mariadb.init = function init () {
     logger.info('init');
 
index a19ba79..f8cd3ab 100644 (file)
@@ -1,26 +1,29 @@
 'use strict';
 /**
- * using websocket
+ * using WebSocket
  */
 
 var fs = require('fs');
 var path = require('path');
+var mkdirp = require('mkdirp');
+var request = require('request');
 var exec = require('child_process').exec;
 var TreeKill = require('tree-kill');
 var util = require('util');
 var JL = require('jsnlog').JL;
-var socketEvent = require('./socketevent');
+var _ = require('lodash');
+var AppConfig = require('../config.json');
 
 var logger = JL('mic.js');
 
-var mic = {};
+var Mic = {};
 var ps = null;
 
-mic.isAvailable = function () {
+Mic.isAvailable = function isAvailable () {
     return (ps === null);
 }
 
-mic.kill = function () {
+Mic.kill = function kill () {
     if (ps === null) {
         return;
     }
@@ -28,8 +31,10 @@ mic.kill = function () {
     ps = null;
 }
 
-mic.process = function (command, callback) {
+Mic.process = function process (command, callback) {
+    // execution
     ps = exec(command);
+
     ps.stdout.on('data', callback.stdout || function (out) {
         process.stdout.write(out);
     });
@@ -40,39 +45,69 @@ mic.process = function (command, callback) {
     ps.on('exit', callback.exit);
 };
 
-mic.create = function (paramObj, io) {
-    logger.info('MIC Create');
+Mic.create = function (paramObj, io, server) {
+    var addr, micCommand;
+    addr = server.address();
+    logger.info('MIC Create: paramObj = ' + JSON.stringify(paramObj));
 
-    var micCommand = 'sudo mic create auto ' + paramObj.pathKsFile + util.format(' --arch %s', 'x86_64') + util.format(' --outdir %s', paramObj.pathOutput);
+    micCommand = 'sudo mic create loop ' + paramObj.pathKsFile + util.format(' --arch %s', 'armv7l') + util.format(' --outdir %s', paramObj.pathOutput + util.format(' --logfile %s', AppConfig.TIC_WEB.LOG_FILE_NAME)) + util.format(' --pack-to %s', AppConfig.TIC_WEB.IMAGE_FILE_NAME));
 
-    function sendMsg(path, msg) {
-        io.sockets.emit(path, msg);
+    function sendMsg(path, msgObj) {
+        io.sockets.emit(path, msgObj);
     }
 
-    mic.process(micCommand, {
-        stdout: function (out) {
-            logger.info(out);
-            sendMsg(socketEvent.FS_IMAGE_ADD_TO, out);
-        },
-        stderr: function (out) {
-            logger.info(out);
-            sendMsg(socketEvent.FS_IMAGE_ADD_TO, out);
-        },
-        error: function (out) {
-            logger.info(out);
-            sendMsg(socketEvent.FS_IMAGE_ADD_FAIL, 'Failed (' + code + ')');
-        },
-        exit: function (code) {
-            // code is the final exit code of the process, otherwise null
-            ps = null;
-            logger.error('Terminated (' + code + ')');
-            if (code === 0) {
-                sendMsg(socketEvent.FS_IMAGE_ADD_FINISH, 'Terminated (' + code + ')');
-            } else {
-                sendMsg(socketEvent.FS_IMAGE_ADD_FAIL, 'Failed (' + code + ')');
+    Mic.process(
+        micCommand,
+        {
+            stdout: function (out) {
+                logger.info(out);
+                sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO, {
+                    msg: out,
+                    jobId: paramObj.jobId
+                });
+            },
+            stderr: function (out) {
+                logger.info(out);
+                sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO, {
+                    msg: out,
+                    jobId: paramObj.jobId
+                });
+            },
+            error: function (out) {
+                logger.info(out);
+                sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FAIL, 'Failed (' + code + ')');
+            },
+            exit: function (code) {
+                // code is the final exit code of the process, otherwise null
+                ps = null;
+                logger.error('Terminated (' + code + ')');
+                if (code === 0) {
+                    sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH, {
+                        msg: 'Terminated (' + code + ')',
+                        jobId: paramObj.jobId,
+                    });
+                } else {
+                    sendMsg(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FAIL, {
+                        msg: 'Failed (' + code + ')',
+                        jobId: paramObj.jobId
+                    });
+                }
             }
         }
-    });
+    );
 };
 
-module.exports = mic;
+Mic.init = function init () {
+    function fnMkdir(paramPath) {
+        mkdirp(paramPath, function (err) {
+            if (err) {
+                logger.error(err);
+            } else {
+                logger.info(paramPath + ' exists');
+            }
+        });
+    }
+    fnMkdir(AppConfig.TIC_WEB.PATH);
+}
+
+module.exports = Mic;
index c8d0d5b..6b7c711 100644 (file)
@@ -2,45 +2,85 @@ var express = require('express');
 var router = express.Router();
 var http = require('http');
 
-var filesystem = require('./filesystem');
+var core = require('./ticcore.js');
 var client = require('./mariadb.js');
-var Config = require('../config.json');
+var AppConfig = require('../config.json');
 
 var JL = require('jsnlog').JL;
 var logger = JL('router.js');
 
+var server;
+
 var init = function init (server) {
-    var server = server;
+    server = server;
+    core.init(server);
+
+    /*******************
+     * JOBS
+     *******************/
+
+    /**
+     * Get The All Jobs
+     * @URI /api/job/list
+     * @TYPE POST
+     */
+    router.post('/job/list', function (req, res) {
+        logger.info('an api called that /api/job/list');
+        client.getJobsAllList(req, res);
+    });
+
+    /**
+     * Get total Count of Jobs
+     * @URI /api/job/count
+     * @TYPE POST
+     */
+    router.post('/job/count', function (req, res) {
+        logger.info('an api called that /api/job/count');
+        client.getJobsTotalCount(req, res);
+    });
 
     /**
-     * FileSystem
+     * Add New Job
+     * @URI /api/job/add
+     * @TYPE POST
      */
+    router.post('/job/add', function (req, res) {
+        logger.info('an api called that /api/job/add');
+        client.addJob(req, res);
+    });
 
     /**
-     * @Deprecated - Use to path of nginx
-     * API
-     *
-     * path : /api/fs/download
-     *
+     * Get The Job By ID
+     * @URI /api/job/:id
+     * @TYPE POST
      */
-    router.get('/fs/download/:filename', function (req, res) {
-        logger.info('an api called that /api/fs/download/'+req.params.filename);
-        filesystem.download(req, res);
+    router.post('/job/:id', function (req, res) {
+        logger.info('an api called that /api/job/' + req.params.id);
+        client.getJobById(req, res);
     });
 
+    /**
+     * Update The Job By ID
+     * @URI /api/job/edit/:id
+     * @TYPE POST
+     */
+    router.post('/job/edit/:id', function (req, res) {
+        logger.info('an api called that /api/job/edit/' + req.params.id);
+        client.editJob(req, res);
+    });
 
     /*******************
-     * IMAGE
+     * IMAGES
      *******************/
 
     /**
-     * Get All images
+     * Get The All Images
      * @URI /api/image/list
      * @TYPE POST
      */
     router.post('/image/list', function (req, res) {
         logger.info('an api called that /api/image/list');
-        client.getAllImages(req, res);
+        client.getImagesAllList(req, res);
     });
 
     /**
@@ -50,7 +90,27 @@ var init = function init (server) {
      */
     router.post('/image/count', function (req, res) {
         logger.info('an api called that /api/image/count');
-        client.getTotalCount(req, res);
+        client.getImagesTotalCount(req, res);
+    });
+
+    /**
+     * Add New Image
+     * @URI /api/image/add
+     * @TYPE POST
+     */
+    router.post('/image/add', function (req, res) {
+        logger.info('an api called that /api/image/add');
+        client.addImage(req, res);
+    });
+
+    /**
+     * Update The Image By ID
+     * @URI /api/image/edit/:id
+     * @TYPE POST
+     */
+    router.post('/image/edit/:id', function (req, res) {
+        logger.info('an api called that /api/image/edit/' + req.params.id);
+        client.editImage(req, res);
     });
 
     /*******************
@@ -64,34 +124,7 @@ var init = function init (server) {
      */
     router.post('/analysis', function (req, res) {
         logger.info('an api called that /api/analysis');
-
-        var postData = JSON.stringify(req.body);
-        var addr = server.address();
-
-        var options = {
-            host: addr.address,
-            port: Config.TIC_CORE.PORT || addr.port + 1,
-            method: 'POST',
-            path: '/analysis',
-            headers: {
-                'Content-Type': 'application/json',
-                'Content-Length': Buffer.byteLength(postData)
-            }
-        };
-
-        var data = '';
-        var ticCoreReq = http.request(options, function (ticCoreRes) {
-            ticCoreRes.setEncoding('utf8');
-            ticCoreRes.on('data', function (chunk) {
-                data += chunk;
-            });
-            ticCoreRes.on('end', function () {
-                res.send(data);
-            });
-        });
-
-        ticCoreReq.write(postData);
-        ticCoreReq.end();
+        core.getAnalysis(req, res);
     });
 
     /**
@@ -100,33 +133,8 @@ var init = function init (server) {
      * @TYPE POST
      */
     router.post('/exports', function (req, res) {
-        var postData = JSON.stringify(req.body);
-        var addr = server.address();
-
-        var options = {
-            host: addr.address,
-            port: Config.TIC_CORE.PORT || addr.port + 1,
-            method: 'POST',
-            path: '/exports',
-            headers: {
-                'Content-Type': 'application/json',
-                'Content-Length': Buffer.byteLength(postData)
-            }
-        };
-
-        var data = '';
-        var ticCoreReq = http.request(options, function (ticCoreRes) {
-            ticCoreRes.setEncoding('utf8');
-            ticCoreRes.on('data', function (chunk) {
-                data += chunk;
-            });
-            ticCoreRes.on('end', function () {
-                res.send(data);
-            });
-        });
-
-        ticCoreReq.write(postData);
-        ticCoreReq.end();
+        logger.info('an api called that /api/exports');
+        core.getExports(req, res);
     });
 
     return router;
index 4c44442..8c22ab6 100644 (file)
@@ -4,8 +4,7 @@ var JL = require('jsnlog').JL;
 var http = require('http');
 var logger = JL('server.js');
 var winston = require('winston');
-var appConfig = require('../config.json');
-var fileSystem = require('./filesystem');
+var AppConfig = require('../config.json');
 
 var start = function start (app) {
     var server = http.createServer(app);
@@ -30,7 +29,7 @@ var start = function start (app) {
             timestamp: _timestamp,
             formatter: _customFormatter,
             json: false,
-            filename: appConfig.TIC_WEB.LOG_FILE,
+            filename: AppConfig.TIC_WEB.LOG_FILE,
             maxsize: 104857600, // 100 MB = 1024 * 1024 * 100 = 104857600 Bytes
             maxFiles: 5
         });
@@ -38,7 +37,6 @@ var start = function start (app) {
 
         logger.info('Server listening at ' + addr.address + ':' + addr.port);
 
-        fileSystem.init();
     });
 
     server.on('error', function(err) {
diff --git a/controller/socketevent.js b/controller/socketevent.js
deleted file mode 100644 (file)
index 8a281b2..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-'use strict';
-
-var SocketEvent = {};
-
-SocketEvent.APP_CONFIG_TO = 'ws/app/config/to';
-SocketEvent.APP_CONFIG_FROM = 'ws/app/config/from';
-
-SocketEvent.MIC_AVAILABLE_TO = 'ws/mic/available/to';
-SocketEvent.MIC_AVAILABLE_FROM = 'ws/mic/available/from';
-
-SocketEvent.FS_IMAGE_LIST_TO = 'ws/fs/image/list/to';
-SocketEvent.FS_IMAGE_LIST_FROM = 'ws/fs/image/list/from';
-
-SocketEvent.FS_IMAGE_ADD_TO = 'ws/fs/image/add/to';
-SocketEvent.FS_IMAGE_ADD_FROM = 'ws/fs/image/add/from';
-SocketEvent.FS_IMAGE_ADD_KILL = 'ws/fs/image/add/kill';
-SocketEvent.FS_IMAGE_ADD_FAIL = 'ws/fs/image/add/fail';
-SocketEvent.FS_IMAGE_ADD_FINISH = 'ws/fs/image/add/finish';
-
-module.exports = SocketEvent;
index e238ecf..19831bd 100644 (file)
@@ -1,72 +1,50 @@
 var socketio = require('socket.io');
 var JL = require('jsnlog').JL;
-var logger = JL('app.js');
-var SocketEvent = require('./socketevent');
+var logger = JL('socketio.js');
+var url = require('url');
 var Mic = require('./mic');
-var fileSystem = require('./filesystem');
-var appConfig = require('../config.json');
+var AppConfig = require('../config.json');
 
 var listen = function listen (server) {
     var io = socketio.listen(server);
 
     /**
-     * filesystem controller (read/create)
      * Connection with MIC
      */
     io.on('connection', function (socket) {
         logger.info('socket connection');
 
         /**
-         * SocketEvent.FS_IMAGE_LIST_FROM = 'ws/fs/image/list/from'
+         * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FROM = 'ws/fs/image/add/from'
          */
-        socket.on(SocketEvent.FS_IMAGE_LIST_FROM, function (data) {
-            var msgData, fileList, targetDirectory;
+        socket.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FROM, function (data) {
+            Mic.create(data, io, server);
 
-            msgData = {};
-            fileList = [];
-            targetDirectory = data.path;
-
-            // get the list of file
-            fileList = fileSystem.list(targetDirectory);
-
-            // set the list
-            msgData.list = fileList;
-
-            // send
-            socket.emit(SocketEvent.FS_IMAGE_LIST_TO, msgData);
+            io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, Mic.isAvailable());
         });
 
         /**
-         * SocketEvent.FS_IMAGE_ADD_FROM = 'ws/fs/image/add/from'
+         * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_KILL = 'ws/fs/image/add/kill'
          */
-        socket.on(SocketEvent.FS_IMAGE_ADD_FROM, function (data) {
-            Mic.create(data, io);
-
-            io.sockets.emit(SocketEvent.MIC_AVAILABLE_TO, Mic.isAvailable());
-        });
-
-        /**
-         * SocketEvent.FS_IMAGE_ADD_KILL = 'ws/fs/image/add/kill'
-         */
-        socket.on(SocketEvent.FS_IMAGE_ADD_KILL, function () {
+        socket.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_KILL, function () {
             Mic.kill();
 
-            io.sockets.emit(SocketEvent.MIC_AVAILABLE_TO, Mic.isAvailable());
+            io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, Mic.isAvailable());
         });
 
         /**
-         * SocketEvent.MIC_AVAILABLE_FROM = 'ws/mic/available/from'
+         * AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM = 'ws/mic/available/from'
          */
-        socket.on(SocketEvent.MIC_AVAILABLE_FROM, function () {
+        socket.on(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM, function () {
             logger.info('mic available: ' + Mic.isAvailable());
-            io.sockets.emit(SocketEvent.MIC_AVAILABLE_TO, Mic.isAvailable());
+            io.sockets.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, Mic.isAvailable());
         });
 
         /**
-         * SocketEvent.APP_CONFIG_FROM = 'ws/app/config/from'
+         * AppConfig.EVENT.SOCKET.APP_CONFIG_FROM = 'ws/app/config/from'
          */
-        socket.on(SocketEvent.APP_CONFIG_FROM, function () {
-            socket.emit(SocketEvent.APP_CONFIG_TO, appConfig);
+        socket.on(AppConfig.EVENT.SOCKET.APP_CONFIG_FROM, function () {
+            socket.emit(AppConfig.EVENT.SOCKET.APP_CONFIG_TO, AppConfig);
         });
 
         socket.on('disconnect', function () {
@@ -75,7 +53,6 @@ var listen = function listen (server) {
 
     });
 
-
     return io;
 };
 
diff --git a/controller/ticcore.js b/controller/ticcore.js
new file mode 100644 (file)
index 0000000..f073ea4
--- /dev/null
@@ -0,0 +1,95 @@
+'use strict';
+
+var mariaSql = require('mariasql');
+var JL = require('jsnlog').JL;
+var logger = JL('mariadb.js');
+var http = require('http');
+var AppConfig = require('../config.json');
+var _ = require('lodash');
+
+/**
+ * ticcore
+ */
+var ticcore = ticcore ||{};
+
+/**
+ * server
+ */
+ticcore.server = null;
+
+/**
+ * initialize
+ */
+ticcore.init = function init (server) {
+    this.server = server;
+};
+
+/**
+ * Get package data from tic-core via RESTful API
+ */
+ticcore.getAnalysis = function getAnalysis (req, res) {
+    var postData = JSON.stringify(req.body);
+    var addr = this.server.address();
+
+    var options = {
+        host: addr.address,
+        port: AppConfig.TIC_CORE.PORT || addr.port + 1,
+        method: 'POST',
+        path: '/analysis',
+        headers: {
+            'Content-Type': 'application/json',
+            'Content-Length': Buffer.byteLength(postData)
+        }
+    };
+
+    var data = '';
+    var ticCoreReq = http.request(options, function (ticCoreRes) {
+        ticCoreRes.setEncoding('utf8');
+        ticCoreRes.on('data', function (chunk) {
+            data += chunk;
+        });
+        ticCoreRes.on('end', function () {
+            res.send(data);
+        });
+    });
+
+    ticCoreReq.write(postData);
+    ticCoreReq.end();
+};
+
+ticcore.getExports = function getExports (req, res) {
+    var postData, addr, options, data, ticCoreReq;
+
+    postData = JSON.stringify(req.body);
+
+    logger.info('getExports: ' + postData);
+
+    addr = this.server.address();
+
+    options = {
+        host: addr.address,
+        port: AppConfig.TIC_CORE.PORT || addr.port + 1,
+        method: 'POST',
+        path: '/exports',
+        headers: {
+            'Content-Type': 'application/json',
+            'Content-Length': Buffer.byteLength(postData)
+        }
+    };
+
+    data = '';
+    ticCoreReq = http.request(options, function (ticCoreRes) {
+        ticCoreRes.setEncoding('utf8');
+        ticCoreRes.on('data', function (chunk) {
+            data += chunk;
+        });
+        ticCoreRes.on('end', function () {
+            res.send(data);
+        });
+    });
+
+    ticCoreReq.write(postData);
+    ticCoreReq.end();
+};
+
+module.exports = ticcore;
\ No newline at end of file
index 214e1c1..72e750a 100644 (file)
@@ -39,7 +39,8 @@
     "jsnlog-nodejs": "~2.22.0",
     "moment": "~2.17.1",
     "tree-kill": "https://github.com/leechwin/node-tree-kill.git#master",
-    "mariasql": "~0.2.6"
+    "mariasql": "~0.2.6",
+    "request": "~2.79.0"
   },
   "devDependencies": {
     "bower": "~1.8.0",
index d2501a8..550c1c2 100644 (file)
@@ -100,6 +100,7 @@ body {
     height: calc(100vh - 210px);
     display: inline-block;
     overflow: auto;
+    width: 100%;
 }
 #tic-job-section .panel-heading .pull-right {
     margin-top: -20px;
@@ -110,6 +111,39 @@ body {
 #tic-job-section .table {
     margin-bottom: 0px;
 }
+#tic-job-list .tic-job-list-btn {
+    float: right;
+    min-width: 10px;
+    padding: 3px 7px;
+    font-size: 12px;
+    font-weight: bold;
+    line-height: 1;
+    color: #fff;
+    text-align: center;
+    white-space: nowrap;
+    vertical-align: middle;
+    border-radius: 10px;
+    background-color: #c3bbbb;
+}
+#tic-job-list .btndownload {
+    background-color: #337ab7;
+}
+#tic-job-list .btncancel {
+    background-color: #020202;
+}
+.extended_job_table_row {
+    border: 1px solid #eee;
+    border-radius: 3px;
+    line-height: 12vh;
+    overflow: scroll;
+    font-size: 12px;
+    background-color: #000;
+    color: #ddd;
+}
+
+.extended_job_table_row td {
+    line-height: 1;
+}
 
 /* Image Page */
 #tic-image-section {
@@ -118,7 +152,7 @@ body {
     background: #e1e1e1;
 }
 
-#tic-image-summary, #tic-image-new-container {
+#tic-image-new-container {
     height: calc(50vh - 183px);
     display: inline-block;
     overflow: auto;
@@ -168,15 +202,6 @@ body {
     overflow: hidden;
 }
 
-#tic-image-new-log {
-    border: 1px solid #eee;
-    border-radius: 3px;
-    height: 32vh;
-    overflow: auto;
-    font-size: 12px;
-}
-
-
 /* Settings Page */
 #tic-settings-section {
     height: 100%;
index 996e185..e191029 100644 (file)
                                                     </tr>
                                                 </thead>
                                                 <tbody>
-                                                    <!--<tr>
-                                                        <td colspan="9">
-                                                            There is no data.
-                                                        </td>
-                                                    </tr>-->
                                                 </tbody>
                                             </table>
                                         </div>
         <section id="tic-image-section">
             <div class="container">
                 <div class="row">
-                    <!-- Image Column -->
-                    <div class="col-md-6">
-                        <div class="panel panel-primary">
-                            <div class="panel-heading">Image</div>
-                            <div class="panel-body">
-                                <table id="tic-image-summary" class="table table-condensed">
-                                    <tbody>
-                                        <tr><td>Image Size</td><td id="tic-image-image-size"></td></tr>
-                                        <tr><td>Image Installed Size</td><td id="tic-image-image-installed-size"></td></tr>
-                                        <tr><td>Package List <span class="badge" id="tic-image-package-list-badge"></span></td><td id="tic-image-package-list"></td></tr>
-                                    </tbody>
-                                </table>
-                            </div>
-                        </div>
-
-                        <div class="panel panel-primary">
-                            <div class="panel-heading">Create Image</div>
-                            <div class="panel-body">
-                                <div id="tic-image-new-log"></div>
-                            </div>
-                            <div class="panel-footer">
-                                <div class="progress hidden" id="tic-image-progress">
-                                    <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%;">Creating image...</div>
-                                </div>
-                                <button type="button" id="tic-image-create" class="btn btn-primary">Create Image</button>
-                                <button type="button" id="tic-image-cancel" class="btn btn-danger hidden">Cancel</button>
-                            </div>
-                        </div>
-                    </div><!-- /End Image Column -->
-
                     <!-- Image List Column -->
-                    <div class="col-md-6">
+                    <div class="col-md-12">
                         <div class="panel panel-primary">
                             <div class="panel-heading">Image List</div>
                             <div class="panel-body">
                                 <ul class="list-group" id="tic-image-list"></ul>
+                                <div id="tic-image-list-pagination">
+                                    <ul class="pagination pagination-sm">
+                                        <li class="disabled"><a href="#"><span class="glyphicon glyphicon-chevron-left"></span></a></li>
+                                        <li class="disabled"><a href="#"><span class="glyphicon glyphicon-chevron-right"></span></a></li>
+                                    </ul>
+                                </div>
                             </div>
                         </div>
                     </div><!-- /End Image List Column -->
index 230c5f5..417d117 100644 (file)
@@ -6,7 +6,6 @@ define([
     'js/page/package',
     'js/page/settings',
     'js/page/image',
-    'js/page/job',
     'js/logger'
 ], function (
     $,
@@ -16,7 +15,6 @@ define([
     Package,
     Settings,
     Image,
-    Job,
     Logger
 ) {
     'use strict';
@@ -44,6 +42,7 @@ define([
             $(".navbar").find(".active").removeClass("active");
             $(this).parent().addClass("active");
         });
+
     }
 
     $(document).ready(function () {
diff --git a/public/src/js/model/ImageModel.js b/public/src/js/model/ImageModel.js
new file mode 100644 (file)
index 0000000..2373e39
--- /dev/null
@@ -0,0 +1,179 @@
+define([
+    'jquery',
+    'lodash',
+    'js/util',
+    'js/logger',
+    ''
+], function (
+    $,
+    _,
+    Util,
+    Logger
+) {
+    'use strict';
+
+    var logger = Logger('model/ImageModel.js');
+
+    // config
+    var AppConfig = null;
+
+    // define the downloadable status
+    var DOWNLOADABLE_STATUS = 'DONE';
+    // define the default status
+    var DEFAULT_STATUS = 'READY';
+
+    // set the config information for the app
+    Util.getAppConfig().then(function (data) {
+        AppConfig = data;
+    });
+
+    var ImageModel = function (paramObj) {
+        this.imageId;
+        this.imageName;
+        this.imageSize;
+        this.imageUptime;
+        this.imageStatus;
+
+        this.imageJobId;
+        this.imageJobPath;
+
+        this.imageHasKsFile;
+        this.imageIsDownload;//{boolean}
+
+        // for the href on a tag
+        this.jobAbsPath;
+        this.jobAbsImagePath;
+        this.jobAbsKsPath;
+        this.jobAbsLogPath;
+
+        this.init(paramObj);
+
+        return this;
+    };
+
+    ImageModel.prototype.init = function (obj) {
+        logger.info('init: ' + JSON.stringify(obj));
+
+        this.setImageId(obj.image_id);
+        this.setImageName(obj.image_name);
+        this.setImageSize(obj.image_size);
+        this.setImageUptime(obj.image_uptime);
+        this.setImageStatus(obj.image_status);
+
+        this.setImageJobId(obj.image_job_id);
+
+        this.setImageHasKsFile(obj.image_hasksfile);
+        this.setImageIsDownload(obj.image_status);
+
+        this.setJobAbsPath();
+        this.setJobAbsImagePath();
+        this.setJobAbsKsPath();
+        this.setJobAbsLogPath();
+    };
+
+    ImageModel.prototype.getJobAbsLogPath = function getJobAbsLogPath () {
+        return this.jobAbsLogPath;
+    };
+
+    ImageModel.prototype.setJobAbsLogPath = function setJobAbsLogPath () {
+        this.jobAbsLogPath = this.getJobAbsPath() + AppConfig.TIC_WEB.LOG_FILE_NAME;
+    };
+
+    ImageModel.prototype.getJobAbsKsPath = function getJobAbsKsPath (value) {
+        return this.jobAbsKsPath = value;
+    };
+
+    ImageModel.prototype.setJobAbsKsPath = function setJobAbsKsPath (value) {
+        this.jobAbsKsPath = value || this.getJobAbsPath() + AppConfig.TIC_WEB.KS_FILE_NAME;
+    };
+
+    ImageModel.prototype.getJobAbsImagePath = function getJobAbsImagePath () {
+        return this.jobAbsImagePath;
+    };
+
+    ImageModel.prototype.setJobAbsImagePath = function setJobAbsImagePath (value) {
+        this.jobAbsImagePath = value || this.getJobAbsPath() + this.getImageName();
+    };
+
+    ImageModel.prototype.getJobAbsPath = function getJobAbsPath (value) {
+        return this.jobAbsPath;
+    };
+
+    ImageModel.prototype.setJobAbsPath = function setJobAbsPath (value) {
+        this.jobAbsPath = value || AppConfig.TIC_WEB.PATH_ABSTRACT + this.getImageJobId() + '/';
+    };
+
+    ImageModel.prototype.getImageIsDownload = function getImageIsDownload () {
+        return this.imageIsDownload;
+    };
+
+    ImageModel.prototype.setImageIsDownload = function setImageIsDownload (value) {
+        var status, isDownloadable;
+
+        isDownloadable = false;
+        status = value || this.getImageStatus();
+
+        if (status === DOWNLOADABLE_STATUS) {
+            isDownloadable = true;
+        }
+        this.imageIsDownload = isDownloadable;
+    };
+
+    ImageModel.prototype.getImageHasKsFile = function getImageHasKsFile () {
+        return this.imageHasKsFile;
+    };
+
+    ImageModel.prototype.setImageHasKsFile = function setImageHasKsFile (value) {
+        this.imageHasKsFile = value || false;
+    };
+
+    ImageModel.prototype.getImageJobId = function getImageJobId (value) {
+        return this.imageJobId;
+    };
+
+    ImageModel.prototype.setImageJobId = function setImageJobId (value) {
+        this.imageJobId = value || 0;
+    };
+
+    ImageModel.prototype.getImageStatus = function getImageStatus () {
+        return this.imageStatus;
+    };
+
+    ImageModel.prototype.setImageStatus = function setImageStatus (value) {
+        this.imageStatus = value || DEFAULT_STATUS;
+    };
+
+    ImageModel.prototype.getImageUptime = function getImageUptime (value) {
+        return this.imageUptime;
+    };
+
+    ImageModel.prototype.setImageUptime = function setImageUptime (value) {
+        this.imageUptime = value || '';
+    };
+
+    ImageModel.prototype.getImageSize = function getImageSize () {
+        return this.imageSize;
+    };
+
+    ImageModel.prototype.setImageSize = function setImageSize (value) {
+        this.imageSize = value ? Util.bytesToSize(value) : '0KB';
+    };
+
+    ImageModel.prototype.getImageName = function getImageName () {
+        return this.imageName;
+    };
+
+    ImageModel.prototype.setImageName = function setImageName (value) {
+        this.imageName = value || '-';
+    };
+
+    ImageModel.prototype.getImageId = function getImageId () {
+        return this.imageId;
+    };
+
+    ImageModel.prototype.setImageId = function setImageId (value) {
+        this.imageId = value;
+    };
+
+    return ImageModel;
+});
index 6e02aba..d7a7e58 100644 (file)
@@ -2,7 +2,8 @@ define([
     'jquery',
     'lodash',
     'js/util',
-    'js/logger'
+    'js/logger',
+    ''
 ], function (
     $,
     _,
@@ -13,13 +14,16 @@ define([
 
     var logger = Logger('model/JobModel.js');
 
+    // config
     var AppConfig = null;
-    Util.getAppConfig()
-    .then(function (data) {
-        AppConfig = data;
-    });
 
-    var JobStatusModel = [
+    // define the downloadable status
+    var DOWNLOADABLE_STATUS = 'DONE';
+    // define the default status
+    var DEFAULT_STATUS = 'READY';
+
+    // describe the all the status of job
+    var JOB_STATUS_LIST = [
         {
             value: 'READY',
             text: 'Ready'
@@ -42,10 +46,12 @@ define([
         }
     ];
 
-    var JobModel = function (paramObj) {
-        logger.info('new JobModel');
+    // set the config information for the app
+    Util.getAppConfig().then(function (data) {
+        AppConfig = data;
+    });
 
-        this.tableIndex;
+    var JobModel = function (paramObj) {
         this.jobId;
         this.jobStatus;
         this.jobStatusText;
@@ -53,26 +59,42 @@ define([
         this.jobImageSize;
         this.jobPath;
         this.jobImagePath;
+        this.jobHasKsFile = false;
         this.jobKsPath;
         this.jobLogPath;
-        this.jobUptime;
         this.isDownload;//{boolean}
 
+        // for the href on a tag
+        this.jobAbsPath;
+        this.jobAbsImagePath;
+        this.jobAbsKsPath;
+        this.jobAbsLogPath;
+        this.jobUptime;
+
         this.init(paramObj);
+
+        return this;
     };
 
     JobModel.prototype.init = function (obj) {
-        logger.info('JobModel.init: ' + JSON.stringify(obj));
+        logger.info('init: ' + JSON.stringify(obj));
 
-        this.setTableIndex(obj.job_index);
         this.setJobId(obj.job_id);
         this.setJobStatus(obj.job_status);
         this.setJobImageName(obj.job_image_name);
         this.setJobImageSize(obj.job_image_size);
+
         this.setJobPath();
         this.setJobImagePath();
+        this.setJobHasKsFile(obj.job_hasksfile);
         this.setJobKsPath();
         this.setJobLogPath();
+
+        this.setJobAbsPath();
+        this.setJobAbsImagePath();
+        this.setJobAbsKsPath();
+        this.setJobAbsLogPath();
+
         this.setJobUptime(obj.job_uptime);
     };
 
@@ -81,7 +103,7 @@ define([
     };
 
     JobModel.prototype.setIsDownload = function (value) {
-        this.isDownload = value;
+        this.isDownload = value || false;
     };
 
     JobModel.prototype.getJobUptime = function () {
@@ -97,7 +119,15 @@ define([
     };
 
     JobModel.prototype.setJobLogPath = function () {
-        this.jobLogPath = this.getJobPath() + '/log.js';
+        this.jobLogPath = this.getJobPath() + AppConfig.TIC_WEB.LOG_FILE_NAME;
+    };
+
+    JobModel.prototype.getJobAbsLogPath = function () {
+        return this.jobAbsLogPath;
+    };
+
+    JobModel.prototype.setJobAbsLogPath = function () {
+        this.jobAbsLogPath = this.getJobAbsPath() + AppConfig.TIC_WEB.LOG_FILE_NAME;
     };
 
     JobModel.prototype.getJobKsPath = function () {
@@ -105,7 +135,23 @@ define([
     };
 
     JobModel.prototype.setJobKsPath = function () {
-        this.jobKsPath = this.getJobPath() + '/ks.js';
+        this.jobKsPath = this.getJobPath() + AppConfig.TIC_WEB.KS_FILE_NAME;
+    };
+
+    JobModel.prototype.getJobAbsKsPath = function () {
+        return this.jobAbsKsPath;
+    };
+
+    JobModel.prototype.setJobAbsKsPath = function () {
+        this.jobAbsKsPath = this.getJobAbsPath() + AppConfig.TIC_WEB.KS_FILE_NAME;
+    };
+
+    JobModel.prototype.getJobHasKsFile = function () {
+        this.jobHasKsFile;
+    };
+
+    JobModel.prototype.setJobHasKsFile = function (value) {
+        this.jobHasKsFile = value || false;
     };
 
     JobModel.prototype.getJobImagePath = function () {
@@ -113,7 +159,7 @@ define([
     };
 
     JobModel.prototype.setJobImagePath = function () {
-        this.jobImagePath = this.getJobPath() + '/' + this.getJobImageName();
+        this.jobImagePath = this.getJobPath() + this.getJobImageName();
     };
 
     JobModel.prototype.getJobImageSize = function () {
@@ -129,7 +175,23 @@ define([
     };
 
     JobModel.prototype.setJobPath = function () {
-        this.jobPath = AppConfig.TIC_WEB.PATH + this.getJobId();
+        this.jobPath = AppConfig.TIC_WEB.PATH + this.getJobId() + '/';
+    };
+
+    JobModel.prototype.getJobAbsImagePath = function () {
+        return this.jobAbsImagePath;
+    };
+
+    JobModel.prototype.setJobAbsImagePath = function () {
+        this.jobAbsImagePath = this.getJobAbsPath() + this.getJobImageName();
+    };
+
+    JobModel.prototype.getJobAbsPath = function () {
+        return this.jobAbsPath;
+    };
+
+    JobModel.prototype.setJobAbsPath = function () {
+        this.jobAbsPath = AppConfig.TIC_WEB.PATH_ABSTRACT + this.getJobId() + '/';
     };
 
     JobModel.prototype.getJobImageName = function () {
@@ -144,28 +206,28 @@ define([
         return this.jobStatusText;
     };
 
+    JobModel.prototype.setJobStatusText = function (value){
+        this.jobStatusText = value || '';
+    };
+
     JobModel.prototype.getJobStatus = function (){
         return this.jobStatus;
     };
 
     JobModel.prototype.setJobStatus = function (status) {
-        /**
-         * FIXME
-         * temporal value -> status
-         */
-        status = 'DONE';
+        var statusInfo, isDownloadable;
+
+        isDownloadable = false;
+        statusInfo = _.find(JOB_STATUS_LIST, {value: status}) || _.find(JOB_STATUS_LIST, {value: DEFAULT_STATUS});
 
-        var statusInfo = _.find(JobStatusModel, {value: status});
+        this.jobStatus = statusInfo.value || '';
+        this.setJobStatusText(statusInfo.text);
 
-        this.jobStatus = statusInfo.value;
-        this.jobStatusText = statusInfo.text;
+        if (this.getJobStatus() === DOWNLOADABLE_STATUS) {
+            isDownloadable = true;
+        }
 
-        /**
-         * TODO :
-         * depends on status
-         * when 'done', can download.
-         */
-        this.setIsDownload(true);
+        this.setIsDownload(isDownloadable);
     };
 
     JobModel.prototype.getJobId = function () {
@@ -173,15 +235,7 @@ define([
     };
 
     JobModel.prototype.setJobId = function (value) {
-        this.jobId = value;
-    };
-
-    JobModel.prototype.getTableIndex = function () {
-        return this.tableIndex;
-    };
-
-    JobModel.prototype.setTableIndex = function (value) {
-        this.tableIndex = value;
+        this.jobId = value || 0;
     };
 
     return JobModel;
index 4680f69..e9100de 100644 (file)
@@ -2,246 +2,172 @@ define([
     'jquery',
     'lodash',
     'js/util',
-    'js/logger'
+    'js/logger',
+    '../model/ImageModel',
+    '../model/JobPagingModel',
+    '../widget/JobPaging',
+    '../widget/ImageEmptyItem',
+    '../widget/ImageItem',
 ], function (
     $,
     _,
     Util,
-    Logger
+    Logger,
+    ImageModel,
+    JobPagingModel,
+    JobPaging,
+    ImageEmptyItem,
+    ImageItem
 ) {
     'use strict';
 
     var logger = Logger('image.js');
 
-    var AppConfig = null;
-
-    // connected socket object
-    var client;
-
-    // the list of checked pakages
-    var checkedPackagesList;
-
-    // template for the URL
-    var URL_EXPORTS = '<%= url %>/api/exports';
-
-    // template
-    var IMAGE_LOG = '<p><%= log %></p>';
-    var IMAGE_ITEM = '<li class="list-group-item image-item">' +
-                        '<p class="image-list-name" title="<%= fileName %>"><%= fileName %></p>' +
-                        '<p class="image-list-detail">Size: <%= fileSize %></p>' +
-                        '<p class="image-list-detail">Updated: <%= fileTime %></p>' +
-                        '<a class="image-list-btndownload" href="<%= hrefPath %>" date-name="<%= fileName %>">Download</a>' +
-                     '</li>';
+    // config
+    var AppConfig;
+
+    // the list for the image
+    var ModelImageList = [];
+
+    // the paging model for the table of job
+    var ModelImagePaging;
+
+    function _update (pageNum) {
+        ModelImageList = [];
+        ModelImagePaging;
+
+        function _updateView (arrImages) {
+            return new Promise(function (resolve, reject) {
+                logger.info('_updateView');
+                var targetBody = $('#tic-image-list');
+                targetBody.empty();
+
+                if (arrImages.length <= 0) {
+                    targetBody.append(new ImageEmptyItem().getTemplate());
+                } else {
+                    // when not empty
+                    _.forEach(arrImages, function (value, index) {
+                        targetBody.append(new ImageItem(value, index).getTemplate());
+                    });
+                }
+            });
+        }
 
-    function _initSocket(socket) {
-        client = socket;
+        function _updateDataModel (result) {
+            return new Promise(function (resolve, reject) {
+                logger.info('_updateDataModel');
 
-        client.emit('ws/mic/available/from');
-        client.on('ws/mic/available/to', function (data) {
-            $('#tic-image-create').prop('disabled', !data);
-            $('#tic-image-progress').toggleClass('hidden', data);
-        });
-
-        client.on('ws/fs/image/list/to', function (data) {
-            var $imageList = $('#tic-image-list').empty();
-            _.forEach(data.list, function (file) {
-                 var imageItem = _.template(IMAGE_ITEM)({
-                    fileName: file.name,
-                    fileSize: Util.bytesToSize(file.size),
-                    fileTime: new Date(file.birthtime).toLocaleString(),
-                    hrefPath: '/tic/images/' + file.name
+                // model
+                _.forEach(result, function (imageItem) {
+                    var item = new ImageModel(imageItem);
+                    ModelImageList.push(item);
                 });
-                $imageList.append(imageItem);
-            });
-        });
-
-        client.on('ws/fs/image/add/to', function (data) {
-            var logItem = _.template(IMAGE_LOG)({
-                log: data
-            });
-            var $imageNewLog = $('#tic-image-new-log').append(logItem);
-            $imageNewLog.animate({ scrollTop : $imageNewLog.prop('scrollHeight') }, 0);
-        });
 
-        // when finish
-        client.on('ws/fs/image/add/finish', function (data) {
-            var logItem = _.template(IMAGE_LOG)({
-                log: 'Image created successfully.'
+                resolve(ModelImageList);
             });
-            var $imageNewLog = $('#tic-image-new-log').append(logItem);
-
-            // notification popup
-            Util.showInfoDialog('Image created successfully.');
-
-            // button enabled
-            $('#tic-image-create').prop('disabled', false);
-            $('#tic-image-cancel').toggleClass('hidden', true);
-            $('#tic-image-progress').toggleClass('hidden', true);
-
-            // upate the list of images
-            updateList();
-        });
+        }
 
-        client.on('ws/fs/image/add/fail', function (data) {
-            var logItem = _.template(IMAGE_LOG)({
-                log: 'Failed to create image.'
-            });
-            var $imageNewLog = $('#tic-image-new-log').append(logItem);
+        function _getAllListItem () {
+            logger.info('_getAllListItem');
+            var msgData = {
+                pageNum: pageNum
+            };
+            return Util.POST(AppConfig.EVENT.IMAGE.IMAGE_GET_ALL_LISTITEM, msgData);
+        }
 
-            // notification popup
-            Util.showAlertDialog('Failed to create image.');
+        function _updatePagingView (dataObj) {
+            return new Promise(function (resolve, reject) {
+                logger.info('_updatePagingView');
 
-            // button enabled
-            $('#tic-image-create').prop('disabled', false);
-            $('#tic-image-cancel').toggleClass('hidden', true);
-            $('#tic-image-progress').toggleClass('hidden', true);
+                var targetPaging = $('#tic-image-list-pagination');
+                targetPaging.empty();
 
-            // upate the list of images
-            updateList();
-        });
+                // create the element
+                targetPaging.append(new JobPaging(dataObj).getTemplate());
 
-    }
+                // bind a events
+                $('#tic-image-section .pagination > li > a').on('click', function(e) {
+                    var pagenum;
 
-    function updateList() {
-        var msgData = {
-            path: AppConfig.MIC.OUT_DIR
-        };
-        client.emit('ws/fs/image/list/from', msgData);
-    }
+                    e.preventDefault();
 
-    function updateSummary() {
-        var pacakgeImageSize = $('#tic-image-image-size').empty();
-        var packageImageInstalledSize = $('#tic-image-image-installed-size').empty();
-        var packageListBadge = $('#tic-image-package-list-badge').empty();
-        var packageList = $('#tic-image-package-list').empty();
+                    pagenum = $(this).data('pagenum');
 
-        checkedPackagesList = require('js/page/package').getCheckedPackages();
-        var count = _.size(checkedPackagesList);
-        var imageSize = _.sumBy(checkedPackagesList, function getImageSize(item) {
-            return _.toNumber(item.size);
-        });
-        var imageInstalledSize = _.sumBy(checkedPackagesList, function getImageInstalled(item) {
-            return _.toNumber(item.installed);
-        });
+                    if (pagenum !== 0) {
+                        gotoPageNum(pagenum);
+                    }
+                    return false;
+                });
 
-        if (_.isNumber(imageSize)) {
-            pacakgeImageSize.html(Util.bytesToSize(imageSize));
-        }
-        if (_.isNumber(imageInstalledSize)) {
-            packageImageInstalledSize.html(Util.bytesToSize(imageInstalledSize));
-        }
-        if (_.isNumber(count)) {
-            packageListBadge.html(count);
-        }
-        if (!_.isEmpty(checkedPackagesList)) {
-            packageList.html(_.orderBy(_.map(checkedPackagesList, 'name')).join('<br>'));
+                resolve();
+            });
         }
 
-        $('#tic-image-create').prop('disabled', count === 0);
-        client.emit('ws/mic/available/from');
-    }
+        function _updatePagingModel (result) {
+            return new Promise(function (resolve, reject) {
+                logger.info('_updatePagingModel');
 
-    function confirmCreateImage() {
-        $('#tic-image-create').prop('disabled', true);
+                var totalCount, pagingCount;
 
-        // when packages are checked nothing
-        if (_.isEmpty(checkedPackagesList)) {
-            return;
-        }
+                // initialize
+                totalCount = 0;
+                $('#tic-image-list-pagination').empty();
 
-        function createImage(pathKsFile) {
-            $('#tic-image-new-log').empty();
+                // set totalCount
+                totalCount = Number(result[0].total_count);
 
-            /**
-             * TODO - checks the msgData
-             */
-            var msgData = {
-                pathKsFile: pathKsFile,
-                pathOutput: AppConfig.MIC.OUT_DIR
-            };
-            client.emit('ws/fs/image/add/from', msgData);
-        }
+                if (_.isEmpty(ModelImagePaging)) {
+                    ModelImagePaging = new JobPagingModel({
+                        totalCount: totalCount,
+                        currentPageNum: pageNum 
+                    })
+                }
 
-        function getExportsUrl() {
-            return _.template(URL_EXPORTS)({
-                url: location.origin
+                resolve(ModelImagePaging);
             });
         }
 
-        function getKickstartRecipeFile() {
-             var msgData = {
-                recipe: {
-                    name: 'default'
-                },
-                packages: _.map(checkedPackagesList, 'name'),
-                output: AppConfig.TIC_WEB.KS_OUT_DIR
-            };
-            return Util.POST(getExportsUrl(), msgData)
-            .then(function (result) {
-                return result.data
-            });
+        function _getTotalCount () {
+            logger.info('_getTotalCount');
+            return Util.POST(AppConfig.EVENT.IMAGE.IMAGE_GET_ALL_COUNT);
         }
 
-        // confirm
-        Util.showConfirmDialog('Are you sure want to create the image?')
-        .then(function () {
-            $('#tic-image-cancel').toggleClass('hidden', false);
-            $('#tic-image-progress').toggleClass('hidden', false);
-            getKickstartRecipeFile()
-            .then(createImage)
-            .catch(function (err) {
-                logger.error(err);
-                Util.showAlertDialog('Failed to create a image.<br>Please check the ks file.');
-                $('#tic-image-create').prop('disabled', false);
-                $('#tic-image-cancel').toggleClass('hidden', true);
-                $('#tic-image-progress').toggleClass('hidden', true);
-            });
-        })
-        .catch(function () {
-            logger.info('Image creation was canceled.');
-            $('#tic-image-create').prop('disabled', false);
-            $('#tic-image-cancel').toggleClass('hidden', true);
-            $('#tic-image-progress').toggleClass('hidden', true);
-        });
+        return _getTotalCount()
+        .then(_updatePagingModel)
+        .then(_updatePagingView)
+        .then(_getAllListItem)
+        .then(_updateDataModel)
+        .then(_updateView);
+    }
+
+    function gotoPageNum (pageNum) {
+        logger.info('gotoPageNum : ' + pageNum);
+        _update(pageNum);
     }
 
-    /**
-     * Initiation for the all widgets
-     */
-    function _initWidgets() {
-        // button
-        $('#tic-image-create').prop('disabled', true).on('click', confirmCreateImage);
+    function updateList(selectedPageNum) {
+        logger.info('updateList');
 
-        function _imageCreateCancel() {
-            client.emit('ws/fs/image/add/kill');
-            $(this).toggleClass('hidden', true);
-        }
-        $('#tic-image-cancel').on('click', _imageCreateCancel);
+        // when first,
+        // the default value of pageNum is 1.
+        var pageNum = selectedPageNum || 1;
+        gotoPageNum(pageNum);
     }
 
     function init() {
         logger.info('init');
 
-        _initWidgets();
-        _initSocket(Util.getWebSocket());
-
-        Util.getAppConfig()
-        .then(function (data) {
+        Util.getAppConfig().then(function (data) {
             AppConfig = data;
             updateList();
         });
     }
+    //-----------------------------------------------------------------------<
 
     init();
 
     return {
         /**
-         * Update summary in image page
-         * @method updateSummary
-         */
-        updateSummary: updateSummary,
-
-        /**
          * Update list in image page
          * @method updateList
          */
index 66cf526..fc2edcf 100644 (file)
@@ -7,7 +7,8 @@ define([
     '../model/JobPagingModel',
     '../widget/JobPaging',
     '../widget/JobTableItem',
-    '../widget/JobTableEmptyItem'
+    '../widget/JobTableEmptyItem',
+    '../widget/JobLog'
 ], function (
     $,
     _,
@@ -17,18 +18,28 @@ define([
     JobPagingModel,
     JobPaging,
     JobTableItem,
-    JobTableEmptyItem
+    JobTableEmptyItem,
+    JobLog
 ) {
     'use strict';
 
     var logger = Logger('job.js');
 
-    var AppConfig = null;
+    // connected socket object
+    var client;
 
-    // global data model -->
+    // config
+    var AppConfig;
+
+    // the list for the job
     var ModelJobList = [];
+
+    // the paging model for the table of job
     var ModelJobPaging;
-    // global data model <--
+
+    // const
+    var JOB_STATUS_DONE = 'DONE';
+    var JOB_STATUS_FAILED = 'FAILED';
 
     function gotoPageNum (pageNum) {
         logger.info('gotoPageNum : ' + pageNum);
@@ -36,14 +47,8 @@ define([
     }
 
     function _update (pageNum) {
-        var msgData;
-
         ModelJobList = [];
         ModelJobPaging;
-        
-        msgData = {
-            pageNum: pageNum
-        };
 
         function _updateView (arrJobs) {
             return new Promise(function (resolve, reject) {
@@ -77,8 +82,11 @@ define([
         }
 
         function _getAllListItem () {
+            var msgData = {
+                pageNum: pageNum
+            };
             logger.info('_getAllListItem');
-            return Util.POST(AppConfig.DATABASE.GET_ALL_LISTITEM, msgData);
+            return Util.POST(AppConfig.EVENT.JOB.JOB_GET_ALL_LISTITEM, msgData);
         }
 
         function _updatePagingView (dataObj) {
@@ -92,7 +100,7 @@ define([
                 targetPaging.append(new JobPaging(dataObj).getTemplate());
 
                 // bind a events
-                $('.pagination > li > a').on('click', function(e) {
+                $('#tic-job-section .pagination > li > a').on('click', function(e) {
                     var pagenum;
 
                     e.preventDefault();
@@ -135,7 +143,7 @@ define([
 
         function _getTotalCount() {
             logger.info('_getTotalCount');
-            return Util.POST(AppConfig.DATABASE.GET_ALL_COUNT);
+            return Util.POST(AppConfig.EVENT.JOB.JOB_GET_ALL_COUNT);
         }
 
         return _getTotalCount()
@@ -147,6 +155,7 @@ define([
     }
 
     function updateList(selectedPageNum) {
+        logger.info('updateList');
         // when first,
         // the default value of pageNum is 1.
         var pageNum = selectedPageNum || 1;
@@ -154,32 +163,178 @@ define([
     }
 
     /**
-     * Initiation for the all widgets
+     * @name doCreateAnImage
+     * @param paramObj {
+     *      jobId: '1',
+     *      pathKsFile: '/var/tmp/tic-web/1/default.ks',
+     *      pathOutput: '/var/tmp/tic-web/1/'
+     * }
      */
-    function _initWidgets() {
-        var jobpanel, filter, tbody;
-
-        jobpanel = $('#tic-job-section');
-        filter = jobpanel.find('.navbar-form');
-        
-        // initial state of filter area
-        filter.hide();
-
-        // when the button that filter clicked
-        $('#tic-job-section .btn-filter').click(function () {
-            filter.slideToggle();
+    function doCreateAnImage (paramObj) {
+        var msgData;
+
+        logger.info('doCreateAnImage');
+
+        msgData = {
+            jobId: paramObj.jobId,
+            pathKsFile: paramObj.pathKsFile,
+            pathOutput: paramObj.pathOutput
+        };
+
+        client.emit(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FROM, msgData);
+
+        updateList(ModelJobPaging.getCurrentPoint());
+    }
+
+    function _initSocket (socket) {
+        // assign
+        client = socket;
+
+        /**
+         * whether can using mic or not
+         *
+         * AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM = 'ws/mic/available/from'
+         * AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO = 'ws/mic/available/to'
+         */
+        client.emit(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_FROM);
+        client.on(AppConfig.EVENT.SOCKET.MIC_AVAILABLE_TO, function (data) {
+            $('#tic-package-create').prop('disabled', !data);
+        });
+
+        /**
+         * when running on mic
+         *
+         * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO = 'ws/fs/image/add/to'
+         */
+        client.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_TO, function (dataObj) {
+            return new JobLog(dataObj);
+        });
+
+        /**
+         * when finish
+         *
+         * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH = 'ws/fs/image/add/finish'
+         */
+        client.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH, function (dataObj) {
+            var jobId, logItem, msgObj;
+
+            // jobId
+            jobId = dataObj.jobId;
+
+            // log
+            logItem = new JobLog(dataObj);
+
+            // log
+            logItem = new JobLog({
+                msg: 'Image created successfully.',
+                jobId: jobId
+            });
+
+            logger.info(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FINISH);
+
+            // button enabled
+            $('#tic-package-create').prop('disabled', false);
+
+            function onError (err) {
+                if (err) {
+                    logger.error(err);
+                    throw err;
+                }
+            }
+
+            function updateJobListView () {
+                // upate the list of jobs
+                updateList(ModelJobPaging.getCurrentPoint());
+
+                // notification popup
+                Util.showInfoDialog('Image created successfully. The #ID is ' + jobId + '.');
+            }
+
+            function updateJobInfo (data) {
+                console.log(data);
+                // update the status and image_id
+                var msgObj = {
+                    job_status: JOB_STATUS_DONE,
+                    image_id: data.image_id
+                };
+                return Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + jobId, msgObj)
+            }
+
+            function addAnImage () {
+                /**
+                 * FIXME
+                 */
+                var msgObj = {
+                    image_name: 'image.tar.gz',
+                    image_type: 'external',
+                    image_size: '92164532'
+                };
+                return Util.POST(AppConfig.EVENT.IMAGE.IMAGE_ADD_ONE, msgObj)
+            }
+
+            function getAnImageInfo () {
+                return new Promise(function (resolve, reject) {
+                    /**
+                     * TODO
+                     *
+                     * Using NGINX
+                     */
+                    resolve();
+                });
+            }
+
+            return getAnImageInfo()
+            .then(addAnImage)
+            .then(updateJobInfo)
+            .then(updateJobListView)
+            .catch(onError);
+        });
+
+        /**
+         * when failed
+         *
+         * AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FAIL = 'ws/fs/image/add/fail'
+         */
+        client.on(AppConfig.EVENT.SOCKET.FS_IMAGE_ADD_FAIL, function (dataObj) {
+            var jobId, logItem, msgObj;
+
+            // jobId
+            jobId = dataObj.jobId;
+
+            // log
+            logItem = new JobLog(dataObj);
+
+            // log
+            logItem = new JobLog({
+                msg: 'Failed to create image.',
+                jobId: jobId
+            });
+
+            // notification popup
+            Util.showAlertDialog('Failed to create image. The #ID is ' + jobId + '.');
+
+            // button enabled
+            $('#tic-package-create').prop('disabled', false);
+
+            // update the status
+            msgObj = {
+                job_status: JOB_STATUS_FAILED
+            };
+            Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + jobId, msgObj)
+            .then(function () {
+                // upate the list of jobs
+                updateList(ModelJobPaging.getCurrentPoint());
+            });
         });
     }
 
-    function init() {
+    function init () {
         logger.info('init');
 
-        _initWidgets();
-
-        // appConfig
-        Util.getAppConfig()
-        .then(function (data) {
+        // set the config information for the app
+        Util.getAppConfig().then(function (data) {
             AppConfig = data;
+            _initSocket(Util.getWebSocket());
             updateList();
         });
     }
@@ -188,10 +343,16 @@ define([
 
     return {
         /**
-         * Update list in image page
+         * Update list in job page
          * @method updateList
          */
-        updateList: updateList
+        updateList: updateList,
+
+        /**
+         * Create an Image
+         * @method doCreateAnImage
+         */
+        doCreateAnImage: doCreateAnImage
     }
 
 });
index 8c5a8df..667a73f 100644 (file)
@@ -3,13 +3,17 @@ define([
     'lodash',
     'js/util',
     'js/page/settings',
-    'js/logger'
+    'js/logger',
+    './job.js',
+    '../model/JobModel'
 ], function (
     $,
     _,
     Util,
     Settings,
-    Logger
+    Logger,
+    Job,
+    JobModel
 ) {
     'use strict';
 
@@ -25,6 +29,143 @@ define([
     var groups = null;
     var groupId = 0;
 
+    // template for the URL
+    var URL_EXPORTS = '<%= url %>/api/exports';
+
+    var JOB_STATUS_INPROGRESS = 'INPROGRESS';
+
+    // AppConfig
+    var AppConfig = null;
+
+    function onClickHandlerForImgCreationBtn () {
+        logger.info('onClickHandlerForImgCreationBtn');
+
+        var checkedPackagesList, checkedPackgaesCount, newJobModel;
+
+        newJobModel = null;
+        checkedPackagesList = _getChecked();
+        checkedPackgaesCount = _.size(checkedPackagesList);
+
+        // if no selected packages
+        if (checkedPackgaesCount === 0) {
+            return;
+        }
+
+        // 'image creation' button is disabled
+        $('#tic-package-create').prop('disabled', true);
+
+        function doConfirmCancel () {
+            new Promise(function (resolve, reject) {
+                logger.info('onClickHandlerForImgCreationBtn.doConfirmCancel');
+                $('#tic-package-create').prop('disabled', false);
+            });
+        }
+
+        function doCreateAnImage () {
+            logger.info('onClickHandlerForImgCreationBtn.doCreateAnImage');
+
+            // scroll
+            $('html, body').animate({
+                scrollTop: $('#tic-job-section').offset().top
+            }, 500);
+
+            // options for the creation
+            var msgData = {
+                jobId: newJobModel.getJobId(),
+                pathKsFile: newJobModel.getJobKsPath(),
+                pathOutput: newJobModel.getJobPath()
+            };
+
+            // create
+            Job.doCreateAnImage(msgData);
+        }
+
+        function getExportsUrl() {
+            var url = _.template(URL_EXPORTS)({
+                url: location.origin
+            });
+
+            logger.info('onClickHandlerForImgCreationBtn.getExportsUrl: ' + url);
+            return url ;
+        }
+
+        function getRecipeFile () {
+            var msgData;
+
+            logger.info('onClickHandlerForImgCreationBtn.getRecipeFile: job_path = ' + newJobModel.getJobPath());
+
+            msgData = {
+                recipe: {
+                    name: 'default'
+                },
+                packages: _.map(checkedPackagesList, 'name'),
+                outdir: newJobModel.getJobPath(),
+                filename: AppConfig.TIC_WEB.KS_FILE_NAME
+            };
+
+            function onErrorGetRecipeFile (err) {
+                logger.info('onClickHandlerForImgCreationBtn.onErrorGetRecipeFile');
+                logger.error(err);
+                $('#tic-package-create').prop('disabled', false);
+                throw err;
+            }
+
+            function onSuccessGetRecipeFile (result) {
+                var msgObj;
+                logger.info('onClickHandlerForImgCreationBtn.onSuccessGetRecipeFile: ' + result.data);
+                msgObj = {
+                    job_status: JOB_STATUS_INPROGRESS,
+                    job_hasksfile: true
+                };
+                return Util.POST(AppConfig.EVENT.JOB.JOB_EDIT_ONE + newJobModel.getJobId(), msgObj);
+            }
+
+            return Util.POST(getExportsUrl(), msgData)
+            .then(onSuccessGetRecipeFile)
+            .catch(onErrorGetRecipeFile);
+        }
+
+        function setJobModel (jobItem) {
+            new Promise(function (resolve, reject) {
+                var jobObj = jobItem[0];
+                newJobModel = new JobModel(jobObj);
+                if (newJobModel) {
+                    resolve(newJobModel);
+                } else {
+                    reject();
+                }
+            });
+        }
+
+        function getJobId (jobItem) {
+            logger.info('onClickHandlerForImgCreationBtn.getJobId');
+            var jobId = jobItem.job_id;
+            return Util.POST(AppConfig.EVENT.JOB.JOB_GET_BYID + jobId);
+        }
+
+        function doConfirmOk () {
+            logger.info('onClickHandlerForImgCreationBtn.doConfirmOk');
+            $('#tic-package-create').prop('disabled', true);
+
+            logger.info('onClickHandlerForImgCreationBtn.addJob');
+            return Util.POST(AppConfig.EVENT.JOB.JOB_ADD_ONE);
+        }
+
+        // confirm dialog
+        function showConfirmDialog () {
+            logger.info('onClickHandlerForImgCreationBtn.showConfirmDialog');
+            return Util.showConfirmDialog('Are you sure want to create an image ?');
+        }
+
+        return showConfirmDialog()
+        .then(doConfirmOk)
+        .then(getJobId)
+        .then(setJobModel)
+        .then(getRecipeFile)
+        .then(doCreateAnImage)
+        .catch(doConfirmCancel);
+    }
+
     function _getChecked() {
         var checkedList = [];
         _.forEach(pkgInfo, function(value, key) {
@@ -667,8 +808,6 @@ define([
         }
 
         $('#tic-package-create').toggleClass('disabled', count === 0);
-
-        require('js/page/image').updateSummary();
     }
 
     /**
@@ -886,39 +1025,11 @@ define([
         });
     }
 
-    function confirmCreateImage () {
-        logger.info('image creation srart');
-        logger.info('confirmCreateImage');
-
-        /**
-         * TODO
-         */
-        function doSomething () {
-            new Promise(function (resolve, reject) {
-                /**
-                 * TODO
-                 *
-                 * maybe add the action that image create button control ?
-                 */
-            });
-        }
-
-        // confirm dialog
-        function showConfirmDialog () {
-            logger.info('showConfirmDialog');
-            return Util.showConfirmDialog('Are you sure want to create an image ?');
-        }
-
-        return showConfirmDialog()
-        .then(doSomething);
-
-    }
-
     function init() {
         logger.info('init');
 
         // button - image creation
-        $('#tic-package-create').on('click', confirmCreateImage);
+        $('#tic-package-create').on('click', onClickHandlerForImgCreationBtn);
 
         function _filter() {
             var filterText = $('#tic-package-toolbar-input').val();
@@ -1021,6 +1132,11 @@ define([
 
         // Patch: Bootstrap dropdown menu not working (not dropping down when clicked)
         $('.dropdown-toggle').dropdown();
+
+        // appConfig
+        Util.getAppConfig().then(function (data) {
+            AppConfig = data;
+        });
     }
 
     init();
diff --git a/public/src/js/widget/ImageEmptyItem.js b/public/src/js/widget/ImageEmptyItem.js
new file mode 100644 (file)
index 0000000..9e1252d
--- /dev/null
@@ -0,0 +1,43 @@
+define([
+    'jquery',
+    'lodash',
+    'js/util',
+    'js/logger'
+], function (
+    $,
+    _,
+    Util,
+    Logger
+) {
+    'use strict';
+
+    var logger = Logger('widget/ImageEmptyItem.js');
+
+    var strEmptyItem = [
+        '<li class="list-group-item">',
+            '<p>There is no data.</p>',
+        '</li>'
+    ];
+
+    var ImageEmptyItem = function () {
+        this.template;
+        this.init();
+        return this;
+    };
+
+    ImageEmptyItem.prototype.init = function () {
+        this.setTemplate();
+    };
+
+    ImageEmptyItem.prototype.getTemplate = function () {
+        return this.template;
+    };
+
+    ImageEmptyItem.prototype.setTemplate = function () {
+        var temp = _.template(_.join(strEmptyItem, ''));
+        this.template = temp({'rowNum': 0});
+    };
+
+    return ImageEmptyItem;
+
+});
diff --git a/public/src/js/widget/ImageItem.js b/public/src/js/widget/ImageItem.js
new file mode 100644 (file)
index 0000000..219bd7f
--- /dev/null
@@ -0,0 +1,67 @@
+define([
+    'jquery',
+    'lodash',
+    'js/util',
+    'js/logger'
+], function (
+    $,
+    _,
+    Util,
+    Logger
+) {
+    'use strict';
+
+    var logger = Logger('widget/ImageItem.js');
+
+    // config
+    var AppConfig = null;
+
+    var strItem = [
+        '<li class="list-group-item image-item">',
+            '<p class="image-list-name" title="<%= imageFileName %>"><%= imageFileName %></p>',
+            '<p class="image-list-detail">Size: <%= fileSize %></p>',
+            '<p class="image-list-detail">Updated: <%= fileTime %></p>',
+            '<div><a class="image-list-btndownload" href="<%= imagePath %>" date-name="<%= imageFileName %>">Download</a></div>',
+            '<div><a class="image-list-btndownload" href="<%= ksPath %>" date-name="<%= ksFileName %>">KS</a></div>',
+            '<div><a class="image-list-btndownload" href="<%= logPath %>" date-name="<%= logFileName %>">Log</a></div>',
+        '</li>'
+    ];
+
+    // set the config information for the app
+    Util.getAppConfig().then(function (data) {
+        AppConfig = data;
+    });
+
+
+    var ImageItem = function (modelObj) {
+        this.model = modelObj;
+        this.template;
+
+        this.init(this.model);
+
+        return this;
+    };
+
+    ImageItem.prototype.init = function () {
+        this.setTemplate(this.model);
+    };
+
+    ImageItem.prototype.getTemplate = function getTemplate () {
+        return this.template;
+    };
+
+    ImageItem.prototype.setTemplate = function setTemplate (item) {
+        this.template = _.template(_.join(strItem, ''))({
+            fileSize: item.getImageSize(),
+            fileTime: new Date(item.setImageUptime()).toLocaleString(),
+            imageFileName: item.getImageName(),
+            ksFileName: AppConfig.TIC_WEB.KS_FILE_NAME,
+            logFileName: AppConfig.TIC_WEB.LOG_FILE_NAME,
+            imagePath: item.getJobAbsImagePath(),
+            ksPath: item.getJobAbsKsPath(),
+            logPath: item.getJobAbsLogPath()
+        });
+    };
+
+    return ImageItem;
+});
diff --git a/public/src/js/widget/JobLog.js b/public/src/js/widget/JobLog.js
new file mode 100644 (file)
index 0000000..090e47f
--- /dev/null
@@ -0,0 +1,48 @@
+define([
+    'jquery',
+    'lodash',
+    'js/util',
+    'js/logger'
+], function (
+    $,
+    _,
+    Util,
+    Logger
+) {
+    'use strict';
+
+    var logger = Logger('widget/JobLog.js');
+
+    var strLog = [
+        '<p><%= log %></p>'
+    ];
+
+    var JobLog = function (logObj) {
+        this.msg = logObj.msg;
+        this.jobId = logObj.jobId;
+        this.template;
+        this.init();
+    };
+
+    JobLog.prototype.init = function () {
+        var logViewId, logViewElem;
+
+        this.template = _.template(strLog)({
+            log: this.msg
+        });
+        logViewId = 'extended_job_table_row_' + this.jobId;
+        logViewElem = $('[id='+logViewId+'] > td');
+        logViewElem.append(this.template);
+        logViewElem.animate({
+            scrollTop: logViewElem.prop('scrollHeight')
+        }, 0);
+
+    };
+
+    JobLog.prototype.getTemplate = function () {
+        return this.template;
+    };
+
+    return JobLog;
+
+});
index 685f3e4..9df2195 100644 (file)
@@ -20,8 +20,6 @@ define([
     ];
 
     var JobTableEmptyItem = function () {
-        logger.info('new JobTableEmptyItem');
-
         this.template;
         this.init();
     };
index 802f4ce..9283bc8 100644 (file)
@@ -19,11 +19,11 @@ define([
             '<td><%= jobStatus %></td>',
             '<td><%= jobImageName %></td>',
             '<td><%= jobImageSize %></td>',
-            '<td><a class="image-list-btndownload" download="download">Download</a></td>',
+            '<td><a class="tic-job-list-btn btndownload" href="<%= jobImagePath %>">Download</a></td>',
             '<td><%= jobUptime %></td>',
-            '<td><button>Cancel</button></td>',
-            '<td><button>KS</button></td>',
-            '<td><button>Log</button></td>',
+            '<td><a class="tic-job-list-btn btncancel">Cancel</a></td>',
+            '<td><a class="tic-job-list-btn" href="<%= jobKsPath %>">KS</a></td>',
+            '<td><a class="tic-job-list-btn" href="<%= jobLogPath %>">Log</a></td>',
         '</tr>'
     ];
 
@@ -33,19 +33,21 @@ define([
             '<td><%= jobStatus %></td>',
             '<td><%= jobImageName %></td>',
             '<td><%= jobImageSize %></td>',
-            '<td><button>Download</button></td>',
+            '<td><a class="tic-job-list-btn btndownload" href="<%= jobImagePath %>">Download</a></td>',
             '<td><%= jobUptime %></td>',
-            '<td><button>Cancel</button></td>',
-            '<td><button>KS</button></td>',
-            '<td><button>Log</button></td>',
-            '<div style="width=100%;height=40px;">TESTTEST</div>',
+            '<td><a class="tic-job-list-btn btncancel">Cancel</a></td>',
+            '<td><a class="tic-job-list-btn" href="<%= jobKsPath %>">KS</a></td>',
+            '<td><a class="tic-job-list-btn" href="<%= jobLogPath %>">Log</a></td>',
+        '</tr>',
+        '<tr id="extended_job_table_row_<%= jobNum %>" class="extended_job_table_row">',
+            '<td colspan="10">',
+            '</td>',
         '</tr>'
     ];
 
-    var JobTableItem = function (modelObj, index) {
-        logger.info('new JobTableItem');
+    var JOB_STATUS_INPROGRESS = 'INPROGRESS';
 
-        this._id = index;
+    var JobTableItem = function (modelObj) {
         this.model = modelObj;
         this.template;
 
@@ -61,7 +63,6 @@ define([
     };
 
     JobTableItem.prototype.setRow = function (item) {
-        logger.info('setRow');
         var data, temp, statusValue, statusText;
 
         data = item || this.model;
@@ -70,33 +71,35 @@ define([
         statusText = data.getJobStatusText();
 
         function createRow () {
-            logger.info('createRow');
-
             temp = _.template(_.join(strRow, ''));
             return temp({
-                'jobNum': data.getTableIndex(),
+                'jobNum': data.getJobId(),
                 'jobStatus': data.getJobStatusText(),
                 'jobImageName': data.getJobImageName(),
                 'jobImageSize': data.getJobImageSize(),
+                'jobImagePath': data.getJobAbsImagePath(),
+                'jobKsPath': data.getJobAbsKsPath(),
+                'jobLogPath': data.getJobAbsLogPath(),
                 'jobUptime': data.getJobUptime()
             });
         }
 
         function createExtendedRow () {
-            logger.info('createExtendedRow');
-
             temp = _.template(_.join(strExtendedRow, ''));
             return temp({
-                'jobNum': data.getTableIndex(),
+                'jobNum': data.getJobId(),
                 'jobStatus': data.getJobStatusText(),
                 'jobImageName': data.getJobImageName(),
                 'jobImageSize': data.getJobImageSize(),
+                'jobImagePath': data.getJobAbsImagePath(),
+                'jobKsPath': data.getJobAbsKsPath(),
+                'jobLogPath': data.getJobAbsLogPath(),
                 'jobUptime': data.getJobUptime()
             });
         }
 
         // when the status is 'in progress'
-        if (statusValue === 'INPROGRESS') {
+        if (statusValue === JOB_STATUS_INPROGRESS) {
             this.template = createExtendedRow();
         } else {
             this.template = createRow();