PageComponent.vala 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using Astralis;
  2. using Inversion;
  3. using Invercargill;
  4. using Invercargill.DataStructures;
  5. namespace Spry {
  6. public abstract class PageComponent : Component, Endpoint {
  7. private Scope scope = inject<Scope>();
  8. public abstract string title { get; }
  9. public async Astralis.HttpResult handle_request (HttpContext http_context, RouteContext route_context) throws Error {
  10. // Register a context for anything that gets instansiated after this
  11. scope.register_local_scoped<PageContext>(() => new PageContext(this));
  12. // Get templates as renderables in order of lowest to highest "rank"
  13. var renderables = scope.get_registrations(typeof(PageTemplate))
  14. .select_many<Pair<Registration, TemplateRoutePrefix>>(r => r.get_metadata<TemplateRoutePrefix>().select_pairs<Registration, TemplateRoutePrefix>(p => r, p => p))
  15. .where(p => p.value2.matches_route(route_context))
  16. .order_by<uint>(p => p.value2.rank)
  17. .attempt_select<Object>(p => scope.resolve_registration (p.value1))
  18. .cast<Renderable>()
  19. .to_series();
  20. // Finally, add this page
  21. renderables.add(this);
  22. MarkupDocument result = null;
  23. foreach (var renderable in renderables) {
  24. var document = yield renderable.to_document();
  25. if(result == null){
  26. result = document;
  27. continue;
  28. }
  29. var content_added = false;
  30. foreach(var outlet in result.select("//spry-content")) {
  31. outlet.replace_with_nodes(document.body.children);
  32. content_added = true;
  33. }
  34. if(content_added && document.head != null) {
  35. result.head.append_nodes(document.head.children);
  36. }
  37. }
  38. return result.to_result(get_status());
  39. }
  40. }
  41. public class PageContext : Object {
  42. public PageComponent component { get; private set; }
  43. public Type page_type { get { return component.get_type(); }}
  44. public string title { get { return component.title; }}
  45. public PageContext(PageComponent component) {
  46. this.component = component;
  47. }
  48. }
  49. }