##// END OF EJS Templates
Add list of available terminals in the dashboard
Thomas Kluyver -
Show More
@@ -0,0 +1,103 b''
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
3
4 define([
5 'base/js/namespace',
6 'base/js/utils',
7 'jquery',
8 'tree/js/notebooklist',
9 ], function(IPython, utils, $, notebooklist) {
10 "use strict";
11
12 var TerminalList = function (selector, options) {
13 // Constructor
14 //
15 // Parameters:
16 // selector: string
17 // options: dictionary
18 // Dictionary of keyword arguments.
19 // base_url: string
20 this.base_url = options.base_url || utils.get_body_data("baseUrl");
21 this.element_name = options.element_name || 'terminal';
22 this.selector = selector;
23 this.terminals = [];
24 if (this.selector !== undefined) {
25 this.element = $(selector);
26 this.style();
27 this.bind_events();
28 this.load_terminals();
29 }
30 };
31
32 TerminalList.prototype = Object.create(notebooklist.NotebookList.prototype);
33
34 TerminalList.prototype.bind_events = function () {
35 var that = this;
36 $('#refresh_' + this.element_name + '_list').click(function () {
37 that.load_terminals();
38 });
39 $('#new_terminal').click($.proxy(this.new_terminal, this));
40 };
41
42 TerminalList.prototype.load_terminals = function() {
43 var that = this;
44 var url = utils.url_join_encode(this.base_url, 'api/terminals');
45 $.ajax(url, {
46 type: "GET",
47 cache: false,
48 dataType: "json",
49 success: $.proxy(this.terminals_loaded, this),
50 error : utils.log_ajax_error
51 });
52 };
53
54 TerminalList.prototype.terminals_loaded = function (data) {
55 this.terminals = data;
56 this.clear_list();
57 var item, path_name, term;
58 for (var i=0; i < this.terminals.length; i++) {
59 term = this.terminals[i];
60 item = this.new_item(-1);
61 this.add_link(term.name, item);
62 this.add_shutdown_button(term.name, item);
63 }
64 $('#terminal_list_header').toggle(data.length === 0);
65 };
66
67 TerminalList.prototype.new_terminal = function() {
68 var url = utils.url_join_encode(this.base_url, 'terminals/new');
69 window.open(url, '_blank');
70 };
71
72 TerminalList.prototype.add_link = function(name, item) {
73 item.data('term-name', name);
74 item.find(".item_name").text(name);
75 item.find(".item_icon").addClass("fa fa-terminal");
76 var link = item.find("a.item_link")
77 .attr('href', utils.url_join_encode(this.base_url, "terminals", name));
78 link.attr('target', '_blank');
79 this.add_shutdown_button(name, item);
80 };
81
82 TerminalList.prototype.add_shutdown_button = function(name, item) {
83 var that = this;
84 var shutdown_button = $("<button/>").text("Shutdown").addClass("btn btn-xs btn-danger").
85 click(function (e) {
86 var settings = {
87 processData : false,
88 type : "DELETE",
89 dataType : "json",
90 success : function () {
91 that.load_terminals();
92 },
93 error : utils.log_ajax_error,
94 };
95 var url = utils.url_join_encode(that.base_url, 'api/terminals', name);
96 $.ajax(url, settings);
97 return false;
98 });
99 item.find(".item_buttons").text("").append(shutdown_button);
100 };
101
102 return {TerminalList: TerminalList};
103 });
@@ -1,115 +1,118 b''
1 // Copyright (c) IPython Development Team.
1 // Copyright (c) IPython Development Team.
2 // Distributed under the terms of the Modified BSD License.
2 // Distributed under the terms of the Modified BSD License.
3
3
4 require([
4 require([
5 'base/js/namespace',
5 'base/js/namespace',
6 'jquery',
6 'jquery',
7 'base/js/events',
7 'base/js/events',
8 'base/js/page',
8 'base/js/page',
9 'base/js/utils',
9 'base/js/utils',
10 'tree/js/notebooklist',
10 'tree/js/notebooklist',
11 'tree/js/clusterlist',
11 'tree/js/clusterlist',
12 'tree/js/sessionlist',
12 'tree/js/sessionlist',
13 'tree/js/kernellist',
13 'tree/js/kernellist',
14 'tree/js/terminallist',
14 'auth/js/loginwidget',
15 'auth/js/loginwidget',
15 // only loaded, not used:
16 // only loaded, not used:
16 'jqueryui',
17 'jqueryui',
17 'bootstrap',
18 'bootstrap',
18 'custom/custom',
19 'custom/custom',
19 ], function(
20 ], function(
20 IPython,
21 IPython,
21 $,
22 $,
22 events,
23 events,
23 page,
24 page,
24 utils,
25 utils,
25 notebooklist,
26 notebooklist,
26 clusterlist,
27 clusterlist,
27 sesssionlist,
28 sesssionlist,
28 kernellist,
29 kernellist,
30 terminallist,
29 loginwidget){
31 loginwidget){
30
32
31 page = new page.Page();
33 page = new page.Page();
32
34
33 var common_options = {
35 var common_options = {
34 base_url: utils.get_body_data("baseUrl"),
36 base_url: utils.get_body_data("baseUrl"),
35 notebook_path: utils.get_body_data("notebookPath"),
37 notebook_path: utils.get_body_data("notebookPath"),
36 };
38 };
37 session_list = new sesssionlist.SesssionList($.extend({
39 session_list = new sesssionlist.SesssionList($.extend({
38 events: events},
40 events: events},
39 common_options));
41 common_options));
40 notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({
42 notebook_list = new notebooklist.NotebookList('#notebook_list', $.extend({
41 session_list: session_list},
43 session_list: session_list},
42 common_options));
44 common_options));
43 cluster_list = new clusterlist.ClusterList('#cluster_list', common_options);
45 cluster_list = new clusterlist.ClusterList('#cluster_list', common_options);
44 kernel_list = new kernellist.KernelList('#running_list', $.extend({
46 kernel_list = new kernellist.KernelList('#running_list', $.extend({
45 session_list: session_list},
47 session_list: session_list},
46 common_options));
48 common_options));
49 terminal_list = new terminallist.TerminalList('#terminal_list', common_options);
47 login_widget = new loginwidget.LoginWidget('#login_widget', common_options);
50 login_widget = new loginwidget.LoginWidget('#login_widget', common_options);
48
51
49 $('#new_notebook').click(function (e) {
52 $('#new_notebook').click(function (e) {
50 notebook_list.new_notebook();
53 notebook_list.new_notebook();
51 });
54 });
52
55
53 var interval_id=0;
56 var interval_id=0;
54 // auto refresh every xx secondes, no need to be fast,
57 // auto refresh every xx secondes, no need to be fast,
55 // update is done at least when page get focus
58 // update is done at least when page get focus
56 var time_refresh = 60; // in sec
59 var time_refresh = 60; // in sec
57
60
58 var enable_autorefresh = function(){
61 var enable_autorefresh = function(){
59 //refresh immediately , then start interval
62 //refresh immediately , then start interval
60 session_list.load_sessions();
63 session_list.load_sessions();
61 cluster_list.load_list();
64 cluster_list.load_list();
62 if (!interval_id){
65 if (!interval_id){
63 interval_id = setInterval(function(){
66 interval_id = setInterval(function(){
64 session_list.load_sessions();
67 session_list.load_sessions();
65 cluster_list.load_list();
68 cluster_list.load_list();
66 }, time_refresh*1000);
69 }, time_refresh*1000);
67 }
70 }
68 };
71 };
69
72
70 var disable_autorefresh = function(){
73 var disable_autorefresh = function(){
71 clearInterval(interval_id);
74 clearInterval(interval_id);
72 interval_id = 0;
75 interval_id = 0;
73 };
76 };
74
77
75 // stop autorefresh when page lose focus
78 // stop autorefresh when page lose focus
76 $(window).blur(function() {
79 $(window).blur(function() {
77 disable_autorefresh();
80 disable_autorefresh();
78 });
81 });
79
82
80 //re-enable when page get focus back
83 //re-enable when page get focus back
81 $(window).focus(function() {
84 $(window).focus(function() {
82 enable_autorefresh();
85 enable_autorefresh();
83 });
86 });
84
87
85 // finally start it, it will refresh immediately
88 // finally start it, it will refresh immediately
86 enable_autorefresh();
89 enable_autorefresh();
87
90
88 page.show();
91 page.show();
89
92
90 // For backwards compatability.
93 // For backwards compatability.
91 IPython.page = page;
94 IPython.page = page;
92 IPython.notebook_list = notebook_list;
95 IPython.notebook_list = notebook_list;
93 IPython.cluster_list = cluster_list;
96 IPython.cluster_list = cluster_list;
94 IPython.session_list = session_list;
97 IPython.session_list = session_list;
95 IPython.kernel_list = kernel_list;
98 IPython.kernel_list = kernel_list;
96 IPython.login_widget = login_widget;
99 IPython.login_widget = login_widget;
97
100
98 events.trigger('app_initialized.DashboardApp');
101 events.trigger('app_initialized.DashboardApp');
99
102
100 // bound the upload method to the on change of the file select list
103 // bound the upload method to the on change of the file select list
101 $("#alternate_upload").change(function (event){
104 $("#alternate_upload").change(function (event){
102 notebook_list.handleFilesUpload(event,'form');
105 notebook_list.handleFilesUpload(event,'form');
103 });
106 });
104
107
105 // set hash on tab click
108 // set hash on tab click
106 $("#tabs").find("a").click(function() {
109 $("#tabs").find("a").click(function() {
107 window.location.hash = $(this).attr("href");
110 window.location.hash = $(this).attr("href");
108 });
111 });
109
112
110 // load tab if url hash
113 // load tab if url hash
111 if (window.location.hash) {
114 if (window.location.hash) {
112 $("#tabs").find("a[href=" + window.location.hash + "]").click();
115 $("#tabs").find("a[href=" + window.location.hash + "]").click();
113 }
116 }
114
117
115 });
118 });
@@ -1,115 +1,137 b''
1 {% extends "page.html" %}
1 {% extends "page.html" %}
2
2
3 {% block title %}{{page_title}}{% endblock %}
3 {% block title %}{{page_title}}{% endblock %}
4
4
5
5
6 {% block stylesheet %}
6 {% block stylesheet %}
7 {{super()}}
7 {{super()}}
8 <link rel="stylesheet" href="{{ static_url("tree/css/override.css") }}" type="text/css" />
8 <link rel="stylesheet" href="{{ static_url("tree/css/override.css") }}" type="text/css" />
9 {% endblock %}
9 {% endblock %}
10
10
11 {% block params %}
11 {% block params %}
12
12
13 data-base-url="{{base_url}}"
13 data-base-url="{{base_url}}"
14 data-notebook-path="{{notebook_path}}"
14 data-notebook-path="{{notebook_path}}"
15
15
16 {% endblock %}
16 {% endblock %}
17
17
18
18
19 {% block site %}
19 {% block site %}
20
20
21 <div id="ipython-main-app" class="container">
21 <div id="ipython-main-app" class="container">
22
22
23 <div id="tab_content" class="tabbable">
23 <div id="tab_content" class="tabbable">
24 <ul id="tabs" class="nav nav-tabs">
24 <ul id="tabs" class="nav nav-tabs">
25 <li class="active"><a href="#notebooks" data-toggle="tab">Notebooks</a></li>
25 <li class="active"><a href="#notebooks" data-toggle="tab">Notebooks</a></li>
26 <li><a href="#running" data-toggle="tab">Running</a></li>
26 <li><a href="#running" data-toggle="tab">Running</a></li>
27 <li><a href="#terminals" data-toggle="tab">Terminals</a></li>
27 <li><a href="#clusters" data-toggle="tab">Clusters</a></li>
28 <li><a href="#clusters" data-toggle="tab">Clusters</a></li>
28 </ul>
29 </ul>
29
30
30 <div class="tab-content">
31 <div class="tab-content">
31 <div id="notebooks" class="tab-pane active">
32 <div id="notebooks" class="tab-pane active">
32 <div id="notebook_toolbar" class="row">
33 <div id="notebook_toolbar" class="row">
33 <div class="col-sm-8 no-padding">
34 <div class="col-sm-8 no-padding">
34 <form id='alternate_upload' class='alternate_upload' >
35 <form id='alternate_upload' class='alternate_upload' >
35 <span id="notebook_list_info" style="position:absolute" >
36 <span id="notebook_list_info" style="position:absolute" >
36 To import a notebook, drag the file onto the listing below or <strong>click here</strong>.
37 To import a notebook, drag the file onto the listing below or <strong>click here</strong>.
37 </span>
38 </span>
38 <input type="file" name="datafile" class="fileinput" multiple='multiple'>
39 <input type="file" name="datafile" class="fileinput" multiple='multiple'>
39 </form>
40 </form>
40 </div>
41 </div>
41 <div class="col-sm-4 no-padding tree-buttons">
42 <div class="col-sm-4 no-padding tree-buttons">
42 <span id="notebook_buttons" class="pull-right">
43 <span id="notebook_buttons" class="pull-right">
43 <button id="new_notebook" title="Create new notebook" class="btn btn-default btn-xs">New Notebook</button>
44 <button id="new_notebook" title="Create new notebook" class="btn btn-default btn-xs">New Notebook</button>
44 <button id="refresh_notebook_list" title="Refresh notebook list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
45 <button id="refresh_notebook_list" title="Refresh notebook list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
45 </span>
46 </span>
46 </div>
47 </div>
47 </div>
48 </div>
48
49
49 <div id="notebook_list">
50 <div id="notebook_list">
50 <div id="notebook_list_header" class="row list_header">
51 <div id="notebook_list_header" class="row list_header">
51 <div id="project_name">
52 <div id="project_name">
52 <ul class="breadcrumb">
53 <ul class="breadcrumb">
53 <li><a href="{{breadcrumbs[0][0]}}"><i class="fa fa-home"></i></a></li>
54 <li><a href="{{breadcrumbs[0][0]}}"><i class="fa fa-home"></i></a></li>
54 {% for crumb in breadcrumbs[1:] %}
55 {% for crumb in breadcrumbs[1:] %}
55 <li><a href="{{crumb[0]}}">{{crumb[1]}}</a></li>
56 <li><a href="{{crumb[0]}}">{{crumb[1]}}</a></li>
56 {% endfor %}
57 {% endfor %}
57 </ul>
58 </ul>
58 </div>
59 </div>
59 </div>
60 </div>
60 </div>
61 </div>
61 </div>
62 </div>
62
63
63 <div id="running" class="tab-pane">
64 <div id="running" class="tab-pane">
64
65
65 <div id="running_toolbar" class="row">
66 <div id="running_toolbar" class="row">
66 <div class="col-sm-8 no-padding">
67 <div class="col-sm-8 no-padding">
67 <span id="running_list_info">Currently running IPython notebooks</span>
68 <span id="running_list_info">Currently running IPython notebooks</span>
68 </div>
69 </div>
69 <div class="col-sm-4 no-padding tree-buttons">
70 <div class="col-sm-4 no-padding tree-buttons">
70 <span id="running_buttons" class="pull-right">
71 <span id="running_buttons" class="pull-right">
71 <button id="refresh_running_list" title="Refresh running list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
72 <button id="refresh_running_list" title="Refresh running list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
72 </span>
73 </span>
73 </div>
74 </div>
74 </div>
75 </div>
75
76
76 <div id="running_list">
77 <div id="running_list">
77 <div id="running_list_header" class="row list_header">
78 <div id="running_list_header" class="row list_header">
78 <div> There are no notebooks running. </div>
79 <div> There are no notebooks running. </div>
79 </div>
80 </div>
80 </div>
81 </div>
81 </div>
82 </div>
82
83
84 <div id="terminals" class="tab-pane">
85
86 <div id="terminal_toolbar" class="row">
87 <div class="col-xs-8 no-padding">
88 <span id="terminal_list_info">Currently running terminals</span>
89 </div>
90 <div class="col-xs-4 no-padding tree-buttons">
91 <span id="terminal_buttons" class="pull-right">
92 <button id="new_terminal" title="New terminal" class="btn btn-default btn-xs">New Terminal</button>
93 <button id="refresh_terminal_list" title="Refresh terminal list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
94 </span>
95 </div>
96 </div>
97
98 <div id="terminal_list">
99 <div id="terminal_list_header" class="row list_header">
100 <div> There are no terminals running. </div>
101 </div>
102 </div>
103 </div>
104
83 <div id="clusters" class="tab-pane">
105 <div id="clusters" class="tab-pane">
84
106
85 <div id="cluster_toolbar" class="row">
107 <div id="cluster_toolbar" class="row">
86 <div class="col-xs-8 no-padding">
108 <div class="col-xs-8 no-padding">
87 <span id="cluster_list_info">IPython parallel computing clusters</span>
109 <span id="cluster_list_info">IPython parallel computing clusters</span>
88 </div>
110 </div>
89 <div class="col-xs-4 no-padding tree-buttons">
111 <div class="col-xs-4 no-padding tree-buttons">
90 <span id="cluster_buttons" class="pull-right">
112 <span id="cluster_buttons" class="pull-right">
91 <button id="refresh_cluster_list" title="Refresh cluster list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
113 <button id="refresh_cluster_list" title="Refresh cluster list" class="btn btn-default btn-xs"><i class="fa fa-refresh"></i></button>
92 </span>
114 </span>
93 </div>
115 </div>
94 </div>
116 </div>
95
117
96 <div id="cluster_list">
118 <div id="cluster_list">
97 <div id="cluster_list_header" class="row list_header">
119 <div id="cluster_list_header" class="row list_header">
98 <div class="profile_col col-xs-4">profile</div>
120 <div class="profile_col col-xs-4">profile</div>
99 <div class="status_col col-xs-3">status</div>
121 <div class="status_col col-xs-3">status</div>
100 <div class="engines_col col-xs-3" title="Enter the number of engines to start or empty for default"># of engines</div>
122 <div class="engines_col col-xs-3" title="Enter the number of engines to start or empty for default"># of engines</div>
101 <div class="action_col col-xs-2">action</div>
123 <div class="action_col col-xs-2">action</div>
102 </div>
124 </div>
103 </div>
125 </div>
104 </div>
126 </div>
105 </div>
127 </div>
106
128
107 </div>
129 </div>
108
130
109 {% endblock %}
131 {% endblock %}
110
132
111 {% block script %}
133 {% block script %}
112 {{super()}}
134 {{super()}}
113
135
114 <script src="{{ static_url("tree/js/main.js") }}" type="text/javascript" charset="utf-8"></script>
136 <script src="{{ static_url("tree/js/main.js") }}" type="text/javascript" charset="utf-8"></script>
115 {% endblock %}
137 {% endblock %}
General Comments 0
You need to be logged in to leave comments. Login now