"JOB_READ_LOG": "/api/job/log/"
},
"PACKAGE": {
- "EXPORT": "/api/exports/"
+ "IMPORT": "/api/imports/",
+ "EXPORT": "/api/exports/",
+ "ANALYSIS": "/api/analysis"
},
"IMAGE": {
"IMAGE_GET_ALL_COUNT": "/api/image/count/",
});
/**
+ * Get recipe data from tic-core via RESTful API
+ * @URI /api/imports
+ * @TYPE POST
+ */
+ router.post('/imports', function (req, res) {
+ logger.info('an api called that /api/imports');
+ core.getImports(req, res);
+ });
+
+ /**
* Get ks file path from tic-core via RESTful API
* @URI /api/exports
* @TYPE POST
ticCoreReq.end();
};
+/**
+ * Get recipe data from tic-core via RESTful API
+ */
+ticcore.getImports = function getImports (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: '/imports',
+ 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.on('error', function (err) {
+ res.send({
+ result: 'false',
+ message: err.message
+ })
+ });
+
+ ticCoreReq.end();
+};
+
ticcore.getExports = function getExports(req, res) {
var postData, addr, options, data, ticCoreReq;
background: #e1e1e1;
}
-#tic-repository-toolbar {
+#tic-settings-recipe-toolbar {
margin-bottom: 10px;
}
opacity: 0.5;
z-index: 2000;
}
-#tic-repository-list li {
+#tic-recipe-list li {
cursor: move;
display: block;
padding: 5px;
background: #eee;
max-width: 100%;
}
-#tic-repository-list li.placeholder {
+#tic-recipe-list li.placeholder {
position: relative;
margin: 0;
padding: 0;
border: none;
content: "";
}
-#tic-repository-list li.placeholder:before {
+#tic-recipe-list li.placeholder:before {
position: absolute;
content: "";
width: 0;
border-left-color: #f00;
border-right: none;
}
-.tic-repository-url {
+.tic-recipe-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
font-size: 11px;
font-weight: bold;
}
+
+
+/* Import Dialog */
+#tic-import-dialog .form-group {
+ margin-bottom: 0px;
+ padding-right: 0px;
+ padding-left: 0px;
+}
<div class="panel panel-primary">
<div class="panel-heading">Settings</div>
<div class="panel-body">
- <!-- Settings Toolbar -->
- <div id="tic-repository-toolbar">
- <button type="button" id="tic-repository-recipe-import" class="btn btn-default"><i class="fa fa-download"></i> Recipe Import</button>
- <button type="button" id="tic-repository-recipe-export" class="btn btn-default"><i class="fa fa-upload"></i> Recipe Export</button>
- </div>
-
<!-- Repository Column -->
<div class="panel panel-primary">
- <div class="panel-heading">Repository</div>
+ <div class="panel-heading">Recipe</div>
<div class="panel-body">
- <div class="input-group">
- <div class="form-group has-feedback has-clear">
- <input id="tic-repository-input" type="text" class="form-control" placeholder="Enter repository URL">
- <span id="tic-repository-input-clear" class="form-control-clear glyphicon glyphicon-remove form-control-feedback hidden"></span>
- </div>
- <span class="input-group-btn">
- <button type="button" id="tic-repository-add"class="btn btn-default">Add Repository</button>
- </span>
+ <!-- Settings Toolbar -->
+ <div id="tic-settings-recipe-toolbar">
+ <button type="button" id="tic-settings-recipe-import" class="btn btn-default"><i class="fa fa-download"></i> Import</button>
+ <button type="button" id="tic-settings-recipe-export" class="btn btn-default"><i class="fa fa-upload"></i> Export</button>
</div>
- <ol id="tic-repository-list" class="list-group"></ol>
+ <ol id="tic-recipe-list" class="list-group"></ol>
</div>
</div>
</div>
<div class="panel-footer">
- <a id="tic-repository-apply" type="button" class="btn btn-primary" href="#tic-package-section">Apply</a>
+ <a id="tic-recipe-apply" type="button" class="btn btn-primary" href="#tic-package-section">Apply</a>
</div>
</div>
</div><!-- /End Settings Column -->
<li class="divider"></li>
-->
</ul>
- </div><!-- /Context menu in package tree -->
+ </div><!-- /End Context menu in package tree -->
+
+ <!-- Import Dialog -->
+ <div class="modal fade" id="tic-import-dialog" tabindex="-1" role="dialog" aria-hidden="true" data-backdrop="static">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h4 class="modal-title">Add Recipe or Repository</h4>
+ </div>
+ <div class="modal-body">
+ <div id="tic-import-recipe-container" data-toggle="validator" data-validate="true">
+ <!-- Recipe File -->
+ <div class="row">
+ <div class="form-group col-md-3">
+ <div class="radio">
+ <label class="radio-inline control-label"><input id="tic-import-recipe-file-group" type="radio" name="recipe" checked="checked"> Recipe File</label>
+ </div>
+ </div>
+ <div class="form-group has-feedback has-clear col-md-5">
+ <input class="form-control tic-import-recipe-file-group" id="tic-import-recipe-file-input" type="text" readonly>
+ </div>
+ <div class="form-group col-md-2">
+ <button id="tic-import-recipe-file-browser" class="tic-import-recipe-file-group btn btn-primary" type="button">Browser..</button>
+ </div>
+ </div>
+
+ <!-- Recipe URL -->
+ <div class="row">
+ <div class="form-group col-md-3">
+ <div class="radio">
+ <label class="radio-inline control-label"><input id="tic-import-recipe-url-group" type="radio" name="recipe"> Recipe URL</label>
+ </div>
+ </div>
+ <div id="tic-import-recipe-url-group" class="form-group has-feedback has-clear col-md-7">
+ <input class="form-control tic-import-recipe-url-group" id="tic-import-recipe-url-input" type="url" placeholder="Enter recipe URL" data-unique="unique">
+ <div id="tic-import-recipe-url-group-help" class="help-block with-errors"></div>
+ </div>
+ </div>
+
+ <!-- Repository URL -->
+ <div class="row">
+ <div class="form-group col-md-3">
+ <div class="radio">
+ <label class="radio-inline control-label"><input id="tic-import-recipe-repo-url-group" type="radio" name="recipe" > Repository URL</label>
+ </div>
+ </div>
+ <div class="form-group has-feedback has-clear col-md-7">
+ <input class="form-control tic-import-recipe-repo-url-group" id="tic-import-recipe-repo-url-input" type="url" placeholder="Enter repository URL" data-unique="unique">
+ <div class="help-block with-errors"></div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button id="tic-import-recipe-confirm-ok" type="button" class="btn btn-primary">OK</button>
+ <button id="tic-import-recipe-confirm-cancel" type="button" class="btn btn-danger" data-dismiss="modal">Cancel</button>
+ </div>
+ </div>
+ </div>
+ </div><!-- /End Import Dialog -->
<!-- library loading -->
<script src="/socket.io/socket.io.js"></script>
<script src="/js/config.js"></script>
<script src="/lib/requirejs/require.js" data-main="js/main"></script>
</body>
-</html>
+</html>
\ No newline at end of file
--- /dev/null
+define([
+ 'jquery',
+ 'lodash',
+ 'js/util',
+ 'js/logger',
+], function (
+ $,
+ _,
+ Util,
+ Logger
+) {
+ 'use strict';
+
+ var logger = Logger('export.js');
+
+ function showExportDialog() {
+ // TODO: show export dialog
+ Util.showAlertDialog('Not yet implemented');
+ }
+
+ function _init() {
+ logger.info('init');
+ }
+
+ _init();
+
+ return {
+ /**
+ * TODO
+ * @method showExportDialog
+ */
+ showExportDialog: showExportDialog
+ }
+
+});
--- /dev/null
+define([
+ 'jquery',
+ 'lodash',
+ 'bootstrap-validator',
+ 'js/util',
+ 'js/logger',
+], function (
+ $,
+ _,
+ BootstrapValidator,
+ Util,
+ Logger
+) {
+ 'use strict';
+
+ var logger = Logger('import.js');
+
+ var CONFIG = null;
+ var recipeStore = [];
+
+ function _getRecipe() {
+ var postBody = {
+ recipes : recipeStore
+ };
+
+ return Util.POST(CONFIG.EVENT.PACKAGE.IMPORT, postBody)
+ .then(function (result) {
+ if (result.result === 'true') {
+ return result.data.recipes;
+ } else {
+ return Promise.reject(result.message);
+ }
+ });
+
+ }
+
+ function showImportDialog(recipes) {
+ _clearUI();
+ recipeStore = _.map(recipes, function(recipe) {
+ return _.pick(recipe,['url','type']);
+ });
+
+ $('#tic-import-dialog').modal('show');
+
+ return new Promise(function (resolve, reject) {
+ // bind event only once
+ $('#tic-import-recipe-confirm-ok').off('click').on('click', function () {
+ var radioId = $("input:radio[name='recipe']:checked").attr('id');
+ var $inputDom = $('.' + radioId);
+ var recipeItem = {
+ url: $inputDom .val(),
+ type: _.includes($inputDom.attr('id'), 'repo') ? 'repository' : 'recipe'
+ }
+ recipeStore.push(recipeItem);
+
+ _getRecipe()
+ .then(function (recipes) {
+ resolve(recipes);
+ $('#tic-import-dialog').modal('hide');
+ })
+ .catch(function (err) {
+ _.remove(recipeStore, function (item) {
+ return item === recipeItem;
+ });
+ $('#tic-import-recipe-confirm-ok').prop('disabled', false);
+
+ $inputDom.parent().removeClass('has-success').addClass('has-error');
+ var helpDomContent = '<ul class="list-unstyled"><li>' + err + '</li></ul>';
+ var helpDomId = '#'+ radioId + '-help';
+ $(helpDomId).append(helpDomContent);
+
+ resolve();
+ })
+ });
+ });
+ }
+
+ function _radioHandler() {
+ $("input:radio[name='recipe']").each(function (index, value) {
+ var classDomQuery = '.' + value.id;
+ $(classDomQuery).each(function (index, dom) {
+ $(dom).prop('disabled', !value.checked);
+ if (value.checked === false ) {
+ if (dom.type === 'url' || dom.type === 'text') {
+ $(dom).val('').change();
+ }
+ }
+ });
+ });
+ }
+
+ function _initUI() {
+ _clearUI();
+
+ $("input:radio[name='recipe']").on('change', _radioHandler);
+ // init for default raido status
+ _radioHandler();
+
+ /* Recipe File */
+ // TODO: brwser button handler
+
+ $('#tic-import-recipe-container').validator({
+ custom: {
+ unique: function($el) {
+ var input = $el.val().trim();
+ if (_.isEmpty(input)) {
+ return;
+ }
+ var duplicatedUrl = _.filter(recipeStore, ['url', input]);
+ if (Util.validateURL(input) && !_.isEmpty(duplicatedUrl)) {
+ $('#tic-import-recipe-confirm-ok').prop('disabled', true);
+ return 'URL is already in use.';
+ } else {
+ $('#tic-import-recipe-confirm-ok').prop('disabled', false);
+ }
+ }
+ }
+ });
+ }
+
+ function _clearUI() {
+ $('#tic-import-recipe-confirm-ok').prop('disabled', true);
+ $("input:radio[id='tic-import-recipe-file-group']").prop('checked', true).change();
+ }
+
+ function _init() {
+ logger.info('init');
+
+ Util.getAppConfig()
+ .then(function (conf) {
+ CONFIG = conf;
+ });
+
+ _initUI();
+ _clearUI();
+ }
+
+ _init();
+
+ return {
+ /**
+ * TODO
+ * @method showImportDialog
+ */
+ showImportDialog: showImportDialog,
+ }
+
+});
'jquery',
'jquery-sortable',
'lodash',
+ 'js/page/import',
+ 'js/page/export',
'js/util',
'js/logger'
], function (
$,
js,
_,
+ Import,
+ Export,
Util,
Logger
) {
var logger = Logger('settings.js');
- // FIXME: make RESTful API URL Table
- var ANALYSIS_URL = '/api/analysis';
- var ROPO_LI = '<li class="list-group-item clearfix"><span class="tic-repository-url"><%= url %></span><button type="button" class="btn pull-right btn-default"><i class="fa fa-trash-o"></i></button></li>';
+ var CONFIG = null;
+ var RECIPE_LI = '<li class="list-group-item clearfix" id="<%= id %>"><span class="tic-recipe-name"><%= name %></span><button type="button" class="btn pull-right btn-default"><i class="fa fa-trash-o"></i></button></li>';
- var repoStore = []; // { name, url }
- var recipeStore = []; // TODO: define repo spec
+ var recipeStore = []; // { url, type, name, , }
- function getRepoStore() {
- return repoStore;
+ function getRecipeStore() {
+ return recipeStore;
}
- function _addRepo(url) {
- $('#tic-repository-list').append(_.template(ROPO_LI)({
- url: url
- }));
+ function _addRecipe(recipe) {
+ var $recipe;
+ if (recipe.type === 'recipe') {
+ $recipe = _.template(RECIPE_LI)({
+ id: recipe.url,
+ name: recipe.name
+ })
+ } else if (recipe.type === 'repository') {
+ $recipe = _.template(RECIPE_LI)({
+ id: recipe.url,
+ name: recipe.url
+ })
+ }
- // TODO: define repo spec
- repoStore.push({
- url: url
- })
+ $('#tic-recipe-list').append($recipe);
}
- // TODO: set/get sortable repo
- function _updateRepo() {
- var $repo = $('#tic-repository-list');
- $repo.empty();
+ // TODO: set/get sortable recipe
+ function _updateRecipe() {
+ var $recipe = $('#tic-recipe-list');
+ $recipe.empty();
- _.forEach(repoStore, function(repo) {
- _addRepo(repo.url);
+ _.forEach(recipeStore, function(recipe) {
+ _addRecipe(recipe);
});
}
function updatePackage() {
+ // FIXME:
var postBody = {
- repos : _.map(_.orderBy(repoStore, ['priority']), 'url'),
- recipes : ['default']
+ //repos : _.map(_.orderBy(recipeStore, ['priority']), 'url'),
+ recipes : recipeStore
};
- return Util.POST(ANALYSIS_URL, postBody)
+ return Util.POST(CONFIG.EVENT.PACKAGE.ANALYSIS, postBody)
.then(function (result) {
if (result.result === 'true') {
- repoStore = result.data.repos;
- _updateRepo();
+ recipeStore = result.data.recipes;
+ _updateRecipe();
return result.data;
} else {
return Promise.reject(result.message);
function init() {
logger.info('init');
- /**
- * Recipe Import/Export
- */
- function _recipeImportBtnHandler() {
- // TODO:
- Util.showAlertDialog('Not yet implemented');
- }
- $('#tic-repository-recipe-import').on('click', _recipeImportBtnHandler);
- function _recipeExportBtnHandler() {
- // TODO:
- Util.showAlertDialog('Not yet implemented');
- }
- $('#tic-repository-recipe-export').on('click', _recipeExportBtnHandler);
+ Util.getAppConfig()
+ .then(function (conf) {
+ CONFIG = conf;
+ });
/**
- * Repository Input Component
+ * Recipe Import/ Export
*/
- function _filter() {
- var input = $(this).val();
- var duplicatedUrl = _.filter(repoStore, ['url', input]);
-
- if (Util.validateURL(input) && _.isEmpty(duplicatedUrl)) {
- $('#tic-repository-add').prop('disabled', false);
- } else {
- $('#tic-repository-add').prop('disabled', true);
- }
- $('#tic-repository-input-clear').toggleClass('hidden', _.isEmpty(input));
+ function _importHandler() {
+ Import.showImportDialog(recipeStore)
+ .then(function(recipes) {
+ recipeStore = recipes;
+ _updateRecipe();
+ });
}
- $('#tic-repository-input').on('input change', _filter);
- function _inputClearBtnHandler() {
- $('#tic-repository-input').val('').trigger('change').focus();
- $(this).toggleClass('hidden', true);
- }
- $('#tic-repository-input-clear').on('click', _inputClearBtnHandler);
+ $('#tic-settings-recipe-import').on('click', _importHandler);
- /**
- * Add Repository Button
- */
- function _addRepoBtnHandler() {
- var $repoInput = $('#tic-repository-input');
- var input = $repoInput.val();
- _addRepo(input);
- $repoInput.val('');
- $('#tic-repository-add').prop('disabled', true);
- $('#tic-repository-input-clear').addClass('hidden');
+ function _exportHandler() {
+ // TODO: export dialog
+ Export.showExportDialog();
}
- $('#tic-repository-add').prop('disabled', true).on('click', _addRepoBtnHandler);
+ $('#tic-settings-recipe-export').on('click', _exportHandler);
/**
- * Remove Repository Button
+ * Remove Recipe Button
*/
- function _removeRepoBtnHandler() {
+ function _removeRecipeBtnHandler() {
var $li = $(this).parent();
- var url = $li.text();
- _.remove(repoStore, function (node) {
- return _.isEqual(node.url, url);
+ var id = $li.attr('id');
+ _.remove(recipeStore, function (node) {
+ return _.isEqual(node.url, id);
});
$li.remove();
}
- $('#tic-repository-list').on('click', 'button', _removeRepoBtnHandler);
+ $('#tic-recipe-list').on('click', 'button', _removeRecipeBtnHandler);
/**
- * Repository List
+ * Recipe List
*/
var adjustment;
- $('#tic-repository-list').sortable({
- group: 'tic-repository-list',
+ $('#tic-recipe-list').sortable({
+ group: 'tic-recipe-list',
pullPlaceholder: false,
// set $item relative to cursor position
/**
* Apply Button
*/
- function _applyRepoBtnHandler() {
+ function _applyRecipeBtnHandler() {
Util.showLoadingDialog(true);
updatePackage()
.then(function(rawData) {
Util.showAlertDialog('Failed to load package list.<br>Please check the tic-core.<br>Error: ' + reason);
});
}
- $('#tic-repository-apply').on('click', _applyRepoBtnHandler);
+ $('#tic-recipe-apply').on('click', _applyRecipeBtnHandler);
}
updatePackage: updatePackage,
/**
- * Get repository data
- * @method getRepoStore
- * @return {array} array of repository object
+ * Get recipe data
+ * @method getRecipeStore
+ * @return {array} array of recipe object
*/
- getRepoStore: getRepoStore
+ getRecipeStore: getRecipeStore
}
-});
+});
\ No newline at end of file