Index: runtime/observatory/lib/src/elements/vm_connect.dart |
diff --git a/runtime/observatory/lib/src/elements/vm_connect.dart b/runtime/observatory/lib/src/elements/vm_connect.dart |
index 37cc2a2a34cb594e067bb4cd9daa8688b4955fd8..8539921608b9b833193bb0eec9848d351614262d 100644 |
--- a/runtime/observatory/lib/src/elements/vm_connect.dart |
+++ b/runtime/observatory/lib/src/elements/vm_connect.dart |
@@ -4,61 +4,174 @@ |
library vm_connect_element; |
-import 'dart:convert'; |
import 'dart:html'; |
+import 'dart:async'; |
+import 'dart:convert'; |
+import 'package:observatory/models.dart' as M; |
+import 'package:observatory/src/elements/helpers/tag.dart'; |
+import 'package:observatory/src/elements/helpers/rendering_scheduler.dart'; |
+import 'package:observatory/src/elements/nav/bar.dart'; |
+import 'package:observatory/src/elements/nav/notify.dart'; |
+import 'package:observatory/src/elements/nav/top_menu.dart'; |
+import 'package:observatory/src/elements/view_footer.dart'; |
+import 'package:observatory/src/elements/vm_connect_target.dart'; |
-import 'observatory_element.dart'; |
-import 'package:observatory/elements.dart'; |
-import 'package:observatory/service_html.dart'; |
-import 'package:polymer/polymer.dart'; |
+class VMConnectElement extends HtmlElement implements Renderable{ |
+ static const tag = const Tag<VMConnectElement>('vm-connect', |
+ dependencies: const [NavBarElement.tag, |
+ NavTopMenuElement.tag, |
+ NavNotifyElement.tag, |
+ ViewFooterElement.tag, |
+ VMConnectTargetElement.tag]); |
-@CustomTag('vm-connect') |
-class VMConnectElement extends ObservatoryElement { |
- @published String standaloneVmAddress = ''; |
+ RenderingScheduler _r; |
- VMConnectElement.created() : super.created() { |
- } |
+ Stream<RenderedEvent<VMConnectElement>> get onRendered => _r.onRendered; |
- void _connect(WebSocketVMTarget target) { |
- app.vm = new WebSocketVM(target); |
- app.locationManager.goForwardingParameters('/vm'); |
+ M.CrashDumpRepository _dump; |
+ M.NotificationRepository _notifications; |
+ M.TargetRepository _targets; |
+ StreamSubscription _targetsSubscription; |
+ |
+ String _address; |
+ |
+ factory VMConnectElement(M.TargetRepository targets, |
+ M.CrashDumpRepository dump, |
+ M.NotificationRepository notifications, |
+ {String address: '', RenderingQueue queue}) { |
+ assert(address != null); |
+ assert(dump != null); |
+ assert(notifications != null); |
+ assert(targets != null); |
+ VMConnectElement e = document.createElement(tag.name); |
+ e._r = new RenderingScheduler(e, queue: queue); |
+ e._address = address; |
+ e._dump = dump; |
+ e._notifications = notifications; |
+ e._targets = targets; |
+ return e; |
} |
+ VMConnectElement.created() : super.created(); |
+ |
@override |
void attached() { |
- super.attached(); |
- var fileInput = shadowRoot.querySelector('#crashDumpFile'); |
- fileInput.onChange.listen(_onCrashDumpFileChange); |
+ super.attached(); _r.enable(); |
+ _targetsSubscription = _targets.onChange.listen((_) => _r.dirty()); |
} |
- String _normalizeStandaloneAddress(String networkAddress) { |
- if (networkAddress.startsWith('ws://')) { |
- return networkAddress; |
- } |
- return 'ws://${networkAddress}/ws'; |
+ @override |
+ void detached() { |
+ super.detached(); children = []; _r.disable(notify: true); |
+ _targetsSubscription.cancel(); _targetsSubscription = null; |
} |
- void connectStandalone(Event e, var detail, Node target) { |
- // Prevent any form action. |
- e.preventDefault(); |
- if (standaloneVmAddress == null) { |
- return; |
- } |
- if (standaloneVmAddress.isEmpty) { |
- return; |
- } |
- var targetAddress = _normalizeStandaloneAddress(standaloneVmAddress); |
- var target = app.targets.findOrMake(targetAddress); |
- _connect(target); |
+ void render() { |
+ children = [ |
+ new NavBarElement(queue: _r.queue) |
+ ..children = [ |
+ new NavTopMenuElement(last: true, queue: _r.queue), |
+ new NavNotifyElement(_notifications, queue: _r.queue) |
+ ], |
+ new DivElement() |
+ ..classes = ['content-centered'] |
+ ..children = [ |
+ new HeadingElement.h1()..text = 'Connect to a Dart VM', |
+ new BRElement(), new HRElement(), |
+ new DivElement() |
+ ..classes = ['flex-row'] |
+ ..children = [ |
+ new DivElement() |
+ ..classes = ['flex-item-40-percent'] |
+ ..children = [ |
+ new HeadingElement.h2()..text = 'WebSocket', |
+ new BRElement(), |
+ new UListElement() |
+ ..children = _targets.list().map((target) { |
+ return new LIElement() |
+ ..children = [new VMConnectTargetElement(target, |
+ current: target == _targets.current, queue: _r.queue) |
+ ..onConnect.listen(_connect) |
+ ..onDelete.listen(_delete) |
+ ]; |
+ }).toList(), |
+ new HRElement(), |
+ new FormElement() |
+ ..autocomplete = 'on' |
+ ..children = [ |
+ _createAddressBox(), |
+ new SpanElement()..text = ' ', |
+ new ButtonElement() |
+ ..classes = ['vm_connect'] |
+ ..text = 'Connect' |
+ ..onClick.listen((e) { |
+ e.preventDefault(); _create(); }), |
+ ], |
+ new BRElement(), |
+ new PreElement() |
+ ..classes = ['well'] |
+ ..text = 'Run Standalone with: \'--observe\'', |
+ new HRElement() |
+ ], |
+ new DivElement() |
+ ..classes = ['flex-item-20-percent'], |
+ new DivElement() |
+ ..classes = ['flex-item-40-percent'] |
+ ..children = [ |
+ new HeadingElement.h2()..text = 'Crash dump', |
+ new BRElement(), |
+ _createCrushDumpLoader(), |
+ new BRElement(), new BRElement(), |
+ new PreElement() |
+ ..classes = ['well'] |
+ ..text = 'Request a crash dump with:\n' |
+ '\'curl localhost:8181/_getCrashDump > dump.json\'', |
+ new HRElement() |
+ ] |
+ ], |
+ ], |
+ new ViewFooterElement(queue: _r.queue) |
+ ]; |
+ } |
+ |
+ TextInputElement _createAddressBox() { |
+ var textbox = new TextInputElement() |
+ ..classes = ['textbox'] |
+ ..placeholder = 'localhost:8181' |
+ ..value = _address |
+ ..onKeyUp |
+ .where((e) => e.key == '\n') |
+ .listen((e) { e.preventDefault(); _create(); }); |
+ textbox.onInput.listen((e) { |
+ _address = textbox.value; |
+ }); |
+ return textbox; |
} |
- _onCrashDumpFileChange(e) { |
- var fileInput = shadowRoot.querySelector('#crashDumpFile'); |
- var reader = new FileReader(); |
- reader.readAsText(fileInput.files[0]); |
- reader.onLoad.listen((_) { |
- var crashDump = JSON.decode(reader.result); |
- app.loadCrashDump(crashDump); |
+ FileUploadInputElement _createCrushDumpLoader() { |
+ FileUploadInputElement e = new FileUploadInputElement() |
+ ..id = 'crashDumpFile'; |
+ e.onChange.listen((_) { |
+ var reader = new FileReader(); |
+ reader.readAsText(e.files[0]); |
+ reader.onLoad.listen((_) { |
+ var crashDump = JSON.decode(reader.result); |
+ _dump.load(crashDump); |
+ }); |
}); |
+ return e; |
+ } |
+ void _create() { |
+ if (_address == null || _address.isEmpty) return; |
+ _targets.add(_normalizeStandaloneAddress(_address)); |
+ } |
+ void _connect(TargetEvent e) => _targets.setCurrent(e.target); |
+ void _delete(TargetEvent e) => _targets.delete(e.target); |
+ |
+ static String _normalizeStandaloneAddress(String networkAddress) { |
+ if (networkAddress.startsWith('ws://')) { |
+ return networkAddress; |
+ } |
+ return 'ws://${networkAddress}/ws'; |
} |
} |