Revision 9ffd10ce
b/ui/static/main.css | ||
---|---|---|
4656 | 4656 |
font-weight: bold; |
4657 | 4657 |
} |
4658 | 4658 |
|
4659 |
.overlay-error .indicator { |
|
4660 |
background-color: #880000; |
|
4661 |
color: #fff; |
|
4662 |
padding: 4px; |
|
4663 |
display: block; |
|
4664 |
float: left; |
|
4665 |
border: 1px solid #444; |
|
4666 |
} |
|
4667 |
|
|
4668 |
.overlay-error .nav-btn:hover { |
|
4669 |
|
|
4670 |
} |
|
4671 |
|
|
4672 |
.overlay-error .nav-btn { |
|
4673 |
margin-left: 5px; |
|
4674 |
color: #fff; |
|
4675 |
display: block; |
|
4676 |
float: left; |
|
4677 |
padding: 4px; |
|
4678 |
background-color: #AAA; |
|
4679 |
border: 1px solid #444; |
|
4680 |
} |
|
4681 |
|
|
4682 |
.overlay-error .error-nav { |
|
4683 |
position: absolute; |
|
4684 |
right: 0px; |
|
4685 |
bottom: -25px; |
|
4686 |
font-size: 0.8em; |
|
4687 |
} |
|
4688 |
|
|
4659 | 4689 |
.overlay-error span.value, .overlay-error div.value { |
4660 | 4690 |
padding: 0.4em; |
4661 | 4691 |
display: block; |
b/ui/static/snf/js/models.js | ||
---|---|---|
423 | 423 |
}, |
424 | 424 |
|
425 | 425 |
rename: function(name, callback) { |
426 |
return this.api.call(this.api_path(), "update", {network:{name:name}}, callback); |
|
426 |
return this.api.call(this.api_path(), "update", { |
|
427 |
network:{name:name}, |
|
428 |
_options:{ |
|
429 |
critical: false, |
|
430 |
error_params:{ |
|
431 |
title: "Network action failed", |
|
432 |
ns: "Networks", |
|
433 |
extra_details: {"Network id": this.id}, |
|
434 |
} |
|
435 |
}}, callback); |
|
427 | 436 |
}, |
428 | 437 |
|
429 | 438 |
get_connectable_vms: function() { |
... | ... | |
805 | 814 |
var url = this.api_path() + "/meta/" + meta.key; |
806 | 815 |
var payload = {meta:{}}; |
807 | 816 |
payload.meta[meta.key] = meta.value; |
817 |
payload._options = { |
|
818 |
critical:false, |
|
819 |
error_params: { |
|
820 |
title: "Machine metadata error", |
|
821 |
extra_details: {"Machine id": this.id} |
|
822 |
}}; |
|
808 | 823 |
|
809 |
// inject error settings |
|
810 |
payload._options = {critical: false}; |
|
811 |
|
|
812 |
this.api.call(url, "update", payload, complete, error) |
|
824 |
this.api.call(url, "update", payload, complete, error); |
|
813 | 825 |
}, |
814 | 826 |
|
815 | 827 |
set_firewall: function(net_id, value, callback, error, options) { |
... | ... | |
976 | 988 |
rename: function(new_name) { |
977 | 989 |
//this.set({'name': new_name}); |
978 | 990 |
this.sync("update", this, { |
991 |
critical: true, |
|
979 | 992 |
data: { |
980 | 993 |
'server': { |
981 | 994 |
'name': new_name |
... | ... | |
1081 | 1094 |
success: function(){ self.handle_action_succeed.apply(self, arguments); success.apply(this, arguments)}, |
1082 | 1095 |
error: function(){ self.handle_action_fail.apply(self, arguments); error.apply(this, arguments)}, |
1083 | 1096 |
error_params: { ns: "Machines actions", |
1084 |
message: "'" + this.get("name") + "'" + " action failed",
|
|
1097 |
title: "'" + this.get("name") + "'" + " " + action + " failed",
|
|
1085 | 1098 |
extra_details: { 'Machine ID': this.id, 'URL': url, 'Action': action || "undefined" }, |
1086 | 1099 |
allow_reload: false |
1087 | 1100 |
}, |
b/ui/static/snf/js/sync.js | ||
---|---|---|
413 | 413 |
|
414 | 414 |
// on api error update the api error_state |
415 | 415 |
api.bind("error", function() { |
416 |
if (snf.api.error_state == snf.api.STATES.ERROR) { return }; |
|
417 |
|
|
416 | 418 |
var args = _.toArray(_.toArray(arguments)[0]); |
417 | 419 |
var params = _.last(args); |
418 | 420 |
|
... | ... | |
420 | 422 |
snf.api.error_state = api.STATES.ERROR; |
421 | 423 |
snf.api.stop_calls = true; |
422 | 424 |
} else { |
423 |
snf.api.error_state = api.STATES.WARN;
|
|
425 |
snf.api.error_state = api.STATES.ERROR;
|
|
424 | 426 |
} |
425 | 427 |
snf.api.trigger("change:error_state", snf.api.error_state); |
426 | 428 |
}); |
b/ui/static/snf/js/ui/web/ui_error_view.js | ||
---|---|---|
52 | 52 |
|
53 | 53 |
this.$(".reload-app").click(function(){ |
54 | 54 |
window.location.reload(true); |
55 |
}) |
|
55 |
}); |
|
56 |
|
|
57 |
this.$(".show-next").click(_.bind(function(){ |
|
58 |
this.show_next_error(); |
|
59 |
}, this)); |
|
60 |
|
|
61 |
this.$(".show-prev").click(_.bind(function(){ |
|
62 |
this.show_prev_error(); |
|
63 |
}, this)); |
|
64 |
|
|
65 |
this.displaying_error = false; |
|
66 |
this.error_stack_index = []; |
|
67 |
this.error_stack = {}; |
|
56 | 68 |
}, |
57 | 69 |
|
58 | 70 |
error_object: function() { |
... | ... | |
62 | 74 |
report_error: function() { |
63 | 75 |
this.feedback_view = this.feedback_view || ui.main.feedback_view; |
64 | 76 |
this.hide(false); |
77 |
this.displaying_error = true; |
|
78 |
|
|
65 | 79 |
window.setTimeout(_.bind(function() { |
66 | 80 |
this.feedback_view.show(this.get_report_message(), true, {error: this.error_object()}); |
67 | 81 |
}, this), 400); |
... | ... | |
81 | 95 |
}, |
82 | 96 |
|
83 | 97 |
show_error: function(ns, code, message, type, details, error_options) { |
84 |
if (snf.api.error_state == snf.api.STATES.NORMAL) { this.error_stack = {} }; |
|
85 |
|
|
98 |
|
|
86 | 99 |
var error_entry = [ns, code, message, type, details, error_options]; |
87 |
this.error_stack[new Date()] = error_entry; |
|
88 |
this.display_error.apply(this, error_entry); |
|
89 |
this.show(); |
|
100 |
var last_error_key = this.update_errors_stack(error_entry); |
|
101 |
|
|
102 |
if (!this.is_visible && !this.displaying_error) { |
|
103 |
this.current_error = last_error_key; |
|
104 |
this.display_error.call(this, last_error_key); |
|
105 |
this.show(); |
|
106 |
} |
|
107 |
|
|
108 |
this.update_errors_stack(); |
|
109 |
}, |
|
110 |
|
|
111 |
update_errors_stack: function(entry) { |
|
112 |
if (snf.api.error_state != snf.api.STATES.ERROR) { |
|
113 |
this.error_stack = {}; |
|
114 |
this.error_stack_index = []; |
|
115 |
}; |
|
116 |
|
|
117 |
var stack_key = (new Date()).getTime(); |
|
118 |
this.error_stack[stack_key] = entry; |
|
119 |
this.error_stack_index.push(stack_key); |
|
120 |
this.errors_occured = this.error_stack_index.length; |
|
121 |
|
|
122 |
this.$(".error-nav").hide(); |
|
123 |
//this.update_errors_stack_layout(); |
|
124 |
return stack_key; |
|
90 | 125 |
}, |
91 | 126 |
|
92 |
display_error: function(ns, code, message, type, details, error_options) { |
|
127 |
is_last_error: function(stack_key) { |
|
128 |
return this.error_stack_index.indexOf(stack_key) == this.error_stack_index.length - 1; |
|
129 |
}, |
|
130 |
|
|
131 |
is_first_error: function(stack_key) { |
|
132 |
return this.error_stack_index.indexOf(stack_key) == 0; |
|
133 |
}, |
|
134 |
|
|
135 |
update_errors_stack_layout: function() { |
|
136 |
if (!this.current_error) { return }; |
|
137 |
|
|
138 |
if (this.errors_occured <= 1) { |
|
139 |
this.$(".error-nav").hide(); |
|
140 |
} else { |
|
141 |
this.$(".error-nav").show(); |
|
142 |
}; |
|
143 |
|
|
144 |
if (this.is_last_error(this.current_error)) { |
|
145 |
this.$(".show-next").hide(); |
|
146 |
} else { |
|
147 |
this.$(".show-next").show(); |
|
148 |
} |
|
149 |
|
|
150 |
if (this.is_first_error(this.current_error)) { |
|
151 |
this.$(".show-prev").hide(); |
|
152 |
} else { |
|
153 |
this.$(".show-prev").show(); |
|
154 |
} |
|
155 |
}, |
|
156 |
|
|
157 |
show_next_error: function() { |
|
158 |
}, |
|
159 |
|
|
160 |
show_prev_error: function() { |
|
161 |
}, |
|
162 |
|
|
163 |
display_error: function(stack_key) { |
|
164 |
var err = this.error_stack[stack_key]; |
|
165 |
var ns = err[0], code = err[1], message = err[2], type = err[3], details = err[4], error_options = err[5] |
|
166 |
|
|
93 | 167 |
this.error_options = {'allow_report': true, 'allow_reload': true, |
94 | 168 |
'extra_details': {}, 'non_critical': false, |
95 |
'allow_details': false }; |
|
169 |
'allow_details': false, |
|
170 |
'allow_close': true }; |
|
96 | 171 |
|
97 | 172 |
if (error_options) { |
98 | 173 |
this.error_options = _.extend(this.error_options, error_options); |
... | ... | |
120 | 195 |
} |
121 | 196 |
|
122 | 197 |
this.$(".actions .show-details").click(); |
198 |
this.$(".error-details").hide(); |
|
123 | 199 |
this.$(".key.details").click(); |
124 | 200 |
this.$(".error-more-details").hide(); |
125 | 201 |
}, |
... | ... | |
170 | 246 |
this.$(".reload-app").hide(); |
171 | 247 |
} |
172 | 248 |
|
249 |
if (this.error_options.allow_close) { |
|
250 |
this.$(".closeme").show(); |
|
251 |
} else { |
|
252 |
this.$(".closeme").hide(); |
|
253 |
} |
|
254 |
|
|
173 | 255 |
}, |
174 | 256 |
|
175 | 257 |
onOpen: function() { |
258 |
this.displaying_error = true; |
|
176 | 259 |
var self = this; |
177 | 260 |
|
178 | 261 |
this.$(".closeme").unbind("click"); |
179 | 262 |
this.$(".closeme").bind("click", function(){ |
180 |
self.hide("reset") |
|
263 |
self.hide("reset");
|
|
181 | 264 |
}) |
182 | 265 |
}, |
183 | 266 |
|
184 | 267 |
hide: function(reset_state) { |
185 |
if (reset_state === "reset") { snf.api.trigger("reset") }; |
|
268 |
if (reset_state === "reset") { |
|
269 |
// delay reset error state for fade out |
|
270 |
window.setTimeout(_.bind(function(){ |
|
271 |
this.displaying_error = false; |
|
272 |
this.error_stack = {}; |
|
273 |
snf.api.trigger("reset"); |
|
274 |
}, this), 500); |
|
275 |
} else { |
|
276 |
this.displaying_error = false; |
|
277 |
} |
|
186 | 278 |
views.ErrorView.__super__.hide.apply(this); |
187 | 279 |
}, |
188 | 280 |
|
b/ui/static/snf/js/ui/web/ui_feedback_view.js | ||
---|---|---|
141 | 141 |
// report error feedback form |
142 | 142 |
if (snf.api.error_state == snf.api.STATES.ERROR) { |
143 | 143 |
snf.api.trigger("reset"); |
144 |
ui.main.error_view.displaying_error = false; |
|
145 |
ui.main.error_view.is_visible = false; |
|
144 | 146 |
} |
145 | 147 |
} |
148 |
ui.main.error_view.is_visible = false; |
|
146 | 149 |
views.FeedbackView.__super__.hide.apply(this); |
147 | 150 |
}, |
148 | 151 |
|
149 | 152 |
show: function(data, collect_data, extra_data, cb) { |
153 |
// proxy error view visibility to avoid showing |
|
154 |
// errors while user sees feedback overlay |
|
155 |
ui.main.error_view.is_visible = true; |
|
156 |
|
|
150 | 157 |
this.data = data || ""; |
151 | 158 |
this.cb = cb || function () {}; |
152 | 159 |
this.collect_data = collect_data || false; |
b/ui/static/snf/js/ui/web/ui_main_view.js | ||
---|---|---|
393 | 393 |
this.error_view.show_error.apply(this.error_view, error_entry); |
394 | 394 |
}, |
395 | 395 |
|
396 |
handle_ui_error: function(error) { |
|
397 |
error = error + "<br /><br />" + snf.util.stacktrace().replace("at", "<br /><br />at"); |
|
398 |
this.error_view.show_error("Application", -1, "Something went wrong", "JS Exception", error); |
|
396 |
handle_ui_error: function(data) { |
|
397 |
var msg = data.msg, code = data.code, err_obj = data.error; |
|
398 |
error = msg + "<br /><br />" + snf.util.stacktrace().replace("at", "<br /><br />at"); |
|
399 |
params = { title: "UI error", extra_details: data.extra }; |
|
400 |
params.allow_close = data.extra.allow_close === undefined ? true : data.extra.allow_close; |
|
401 |
this.error_view.show_error("UI", -1, msg, "JS Exception", error, params); |
|
399 | 402 |
}, |
400 | 403 |
|
401 | 404 |
init_overlays: function() { |
... | ... | |
622 | 625 |
window.positionFooter(); |
623 | 626 |
this.multiple_actions_view.fix_position(); |
624 | 627 |
}, this)); |
625 |
} catch (err) {snf.ui.trigger("error", err)}
|
|
628 |
} catch (err) {snf.ui.trigger_error(-1, "Cannot add view", err)}
|
|
626 | 629 |
} |
627 | 630 |
} else { |
628 | 631 |
} |
... | ... | |
690 | 693 |
}, |
691 | 694 |
|
692 | 695 |
show_view: function(view_id) { |
693 |
// same view, visible |
|
694 |
// get out of here asap |
|
695 |
if (this.current_view && |
|
696 |
this.current_view.id == view_id && |
|
697 |
this.current_view.visible()) { |
|
698 |
return; |
|
699 |
} |
|
700 |
|
|
701 |
// choose proper view_id |
|
702 |
view_id = this.identify_view(view_id); |
|
703 |
|
|
704 |
// add/create view and update current view |
|
705 |
var view = this.add_view(view_id); |
|
706 |
|
|
707 |
// set current view |
|
708 |
this.current_view = view; |
|
709 |
this.current_view_id = view_id; |
|
710 |
|
|
711 |
// hide all other views |
|
712 |
this.hide_views([this.current_view]); |
|
713 |
|
|
714 |
// FIXME: depricated |
|
715 |
$(".large-spinner").remove(); |
|
716 |
|
|
717 |
storage.vms.reset_pending_actions(); |
|
718 |
storage.vms.stop_stats_update(); |
|
719 |
|
|
720 |
// show current view |
|
721 |
this.show_view_pane(); |
|
722 |
view.show(); |
|
723 |
|
|
724 |
// update menus |
|
725 |
if (this.select_view) { |
|
726 |
this.select_view.update_layout(); |
|
727 |
} |
|
728 |
this.current_view.__update_layout(); |
|
696 |
try { |
|
697 |
// same view, visible |
|
698 |
// get out of here asap |
|
699 |
if (this.current_view && |
|
700 |
this.current_view.id == view_id && |
|
701 |
this.current_view.visible()) { |
|
702 |
return; |
|
703 |
} |
|
704 |
|
|
705 |
// choose proper view_id |
|
706 |
view_id = this.identify_view(view_id); |
|
707 |
|
|
708 |
// add/create view and update current view |
|
709 |
var view = this.add_view(view_id); |
|
710 |
|
|
711 |
// set current view |
|
712 |
this.current_view = view; |
|
713 |
this.current_view_id = view_id; |
|
714 |
|
|
715 |
// hide all other views |
|
716 |
this.hide_views([this.current_view]); |
|
717 |
|
|
718 |
// FIXME: depricated |
|
719 |
$(".large-spinner").remove(); |
|
720 |
|
|
721 |
storage.vms.reset_pending_actions(); |
|
722 |
storage.vms.stop_stats_update(); |
|
723 |
|
|
724 |
// show current view |
|
725 |
this.show_view_pane(); |
|
726 |
view.show(); |
|
727 |
|
|
728 |
// update menus |
|
729 |
if (this.select_view) { |
|
730 |
this.select_view.update_layout(); |
|
731 |
} |
|
732 |
this.current_view.__update_layout(); |
|
733 |
|
|
734 |
// update cookies |
|
735 |
this.update_session(); |
|
736 |
|
|
737 |
// machines view subnav |
|
738 |
if (this.current_view.vms_view) { |
|
739 |
$("#machines-pane").show(); |
|
740 |
} else { |
|
741 |
$("#machines-pane").hide(); |
|
742 |
} |
|
743 |
|
|
744 |
// fix footer position |
|
745 |
// TODO: move footer handlers in |
|
746 |
// main view (from home.html) |
|
747 |
if (window.positionFooter) { |
|
748 |
window.positionFooter(); |
|
749 |
} |
|
729 | 750 |
|
730 |
// update cookies |
|
731 |
this.update_session(); |
|
732 |
|
|
733 |
// machines view subnav |
|
734 |
if (this.current_view.vms_view) { |
|
735 |
$("#machines-pane").show(); |
|
736 |
} else { |
|
737 |
$("#machines-pane").hide(); |
|
751 |
// trigger view change event |
|
752 |
this.trigger("view:change", this.current_view.view_id); |
|
753 |
$(window).trigger("view:change"); |
|
754 |
return view; |
|
755 |
} catch (err) { |
|
756 |
snf.ui.trigger_error(-2, "Cannot show view: " + view_id, err); |
|
738 | 757 |
} |
739 |
|
|
740 |
// fix footer position |
|
741 |
// TODO: move footer handlers in |
|
742 |
// main view (from home.html) |
|
743 |
if (window.positionFooter) { |
|
744 |
window.positionFooter(); |
|
745 |
} |
|
746 |
|
|
747 |
// trigger view change event |
|
748 |
this.trigger("view:change", this.current_view.view_id); |
|
749 |
$(window).trigger("view:change"); |
|
750 |
return view; |
|
751 | 758 |
}, |
752 | 759 |
|
753 | 760 |
reset_vm_actions: function() { |
... | ... | |
781 | 788 |
} |
782 | 789 |
|
783 | 790 |
snf.ui.init = function() { |
791 |
window.onerror = function(msg, file, line) { |
|
792 |
snf.ui.trigger_error("CRITICAL", msg, {}, { file:file + ":" + line, allow_close: false }); |
|
793 |
}; |
|
784 | 794 |
snf.ui.main.load(); |
785 | 795 |
} |
786 | 796 |
|
b/ui/static/snf/js/ui/web/ui_vms_base_view.js | ||
---|---|---|
550 | 550 |
return os_icon_tag(vm.get_os(), size, vm.is_active(), attrs); |
551 | 551 |
} |
552 | 552 |
|
553 |
|
|
553 | 554 |
snf.ui = _.extend(snf.ui, bb.Events); |
555 |
snf.ui.trigger_error = function(code, msg, error, extra) { |
|
556 |
snf.ui.trigger("error", { code:code, msg:msg, error:error, extra:extra || {} }) |
|
557 |
}; |
|
554 | 558 |
|
555 | 559 |
})(this); |
b/ui/static/snf/js/utils.js | ||
---|---|---|
56 | 56 |
var data = {} |
57 | 57 |
|
58 | 58 |
try { |
59 |
data.client = {'browser': $.browser, 'screen': $.extend({}, screen), 'client': $.client} |
|
60 |
} catch (err) { data.client = err } |
|
61 |
try { |
|
59 | 62 |
data.calls = synnefo.api.requests; |
60 | 63 |
} catch (err) { data.calls = err } |
61 | 64 |
try { |
... | ... | |
68 | 71 |
data.data.vms = synnefo.storage.vms.toJSON(); |
69 | 72 |
} catch (err) { data.data.vms = err } |
70 | 73 |
try { |
71 |
data.data.networks = synnefo.storage.vms.toJSON();
|
|
74 |
data.data.networks = synnefo.storage.networks.toJSON();
|
|
72 | 75 |
} catch (err) { data.data.networks = err } |
73 |
try { |
|
74 |
data.data.images = synnefo.storage.images.toJSON(); |
|
75 |
} catch (err) { data.data.images = err } |
|
76 |
try { |
|
77 |
data.data.flavors = synnefo.storage.flavors.toJSON(); |
|
78 |
} catch (err) { data.data.flavors = err } |
|
76 |
//try {
|
|
77 |
//data.data.images = synnefo.storage.images.toJSON();
|
|
78 |
//} catch (err) { data.data.images = err }
|
|
79 |
//try {
|
|
80 |
//data.data.flavors = synnefo.storage.flavors.toJSON();
|
|
81 |
//} catch (err) { data.data.flavors = err }
|
|
79 | 82 |
try { |
80 | 83 |
data.date = new Date; |
81 | 84 |
} catch (err) { data.date = err } |
b/ui/static/snf/js/views.js | ||
---|---|---|
119 | 119 |
|
120 | 120 |
this.overlay = $(this.el).overlay(); |
121 | 121 |
this.append_css = this.options ? this.options.css_class ? this.options.css_class : "" : ""; |
122 |
|
|
123 |
this.is_visible = false; |
|
122 | 124 |
return this; |
123 | 125 |
}, |
124 | 126 |
|
... | ... | |
169 | 171 |
}, |
170 | 172 |
|
171 | 173 |
_beforeOpen: function() { |
174 |
this.is_visible = true; |
|
172 | 175 |
if (this.append_css) { |
173 | 176 |
$(this.el).addClass(this.append_css); |
174 | 177 |
} |
... | ... | |
194 | 197 |
}, |
195 | 198 |
|
196 | 199 |
_beforeClose: function() { |
200 |
this.is_visible = false; |
|
197 | 201 |
this.beforeClose.apply(this, arguments); |
198 | 202 |
this.options.beforeClose.apply(this, arguments); |
199 | 203 |
}, |
... | ... | |
224 | 228 |
|
225 | 229 |
// do we need to wait for other overlays to close ??? |
226 | 230 |
if (hidden) { delay = 300; } else { delay = 0; } |
231 |
|
|
232 |
this.is_visible = true; |
|
227 | 233 |
window.setTimeout(_.bind(function(){ this.overlay.load() }, this), delay) |
228 | 234 |
return this; |
229 | 235 |
}, |
b/ui/templates/home.html | ||
---|---|---|
419 | 419 |
</div> |
420 | 420 |
|
421 | 421 |
<div id="error-overlay-content" class="hidden"> |
422 |
<div class="error-nav hidden clearfix"> |
|
423 |
<span class="indicator"><span class="num">1</span> <span |
|
424 |
class="ind-msg">new error occured</span></span> |
|
425 |
<span class="show-next nav-btn">{% trans "next" %}</span> |
|
426 |
<span class="show-prev nav-btn">{% trans "previous" %}</span> |
|
427 |
</div> |
|
422 | 428 |
<div class="message"><p></p></div> |
423 | 429 |
<div class="error-details"> |
424 | 430 |
<span class="key">{% trans "Module" %}</span> |
Also available in: Unified diff