def _render_workflows(request: HttpRequest, **kwargs) -> TemplateResponse: ctx = JsonizeContext(request.locale_id, {}) workflows = list( Workflow.objects.filter( **kwargs).filter(Q(lesson_slug__isnull=True) | Q(lesson_slug="")).prefetch_related( "acl", "owner").order_by("-updated_at")) clientside_workflows = [ w.to_clientside(include_tab_slugs=False, include_block_slugs=False) for w in workflows ] json_workflows = [ jsonize_clientside_workflow(w, ctx, is_init=True) for w in clientside_workflows ] if request.user.is_anonymous: json_user = None else: with transaction.atomic(): lock_user_by_id(request.user.id, for_write=False) json_user = jsonize_clientside_user( query_clientside_user(request.user.id)) init_state = { "loggedInUser": json_user, "workflows": json_workflows, } return TemplateResponse(request, "workflows.html", {"initState": init_state})
def _get_workflow_as_clientside_update(self) -> WorkflowUpdateData: """Return (clientside.Update, delta_id). Raise Workflow.DoesNotExist if a race deletes the Workflow. """ with self._lookup_requested_workflow_with_auth_and_cooperative_lock( ) as workflow: if self.scope["user"].is_anonymous: user = None else: user_id = self.scope["user"].id lock_user_by_id(user_id, for_write=False) user = query_clientside_user(user_id) update = clientside.Update( user=user, workflow=workflow.to_clientside(), tabs={ tab.slug: tab.to_clientside() for tab in workflow.live_tabs }, steps={ step.id: step.to_clientside() for step in Step.live_in_workflow(workflow) }, ) return WorkflowUpdateData(update, workflow.last_delta_id)
def make_init_state(request, workflow: Workflow, modules: Dict[str, ModuleZipfile]) -> Dict[str, Any]: """Build a dict to embed as JSON in `window.initState` in HTML. Raise Http404 if the workflow disappeared. Side-effect: update workflow.last_viewed_at. """ try: with workflow.cooperative_lock(): # raise DoesNotExist on race if request.user.is_anonymous: user = None else: lock_user_by_id(request.user.id, for_write=False) user = query_clientside_user(request.user.id) workflow.last_viewed_at = datetime.datetime.now() workflow.save(update_fields=["last_viewed_at"]) state = clientside.Init( user=user, workflow=workflow.to_clientside(), tabs={ tab.slug: tab.to_clientside() for tab in workflow.live_tabs }, steps={ step.id: step.to_clientside( force_module_zipfile=modules.get(step.module_id_name)) for step in Step.live_in_workflow( workflow).prefetch_related("tab") }, modules={ module_id: clientside.Module( spec=module.get_spec(), js_module=module.get_optional_js_module(), ) for module_id, module in modules.items() }, blocks={ block.slug: block.to_clientside() for block in workflow.blocks.all() }, settings={ "bigTableRowsPerTile": settings.BIG_TABLE_ROWS_PER_TILE, "bigTableColumnsPerTile": settings.BIG_TABLE_COLUMNS_PER_TILE, }, ) except Workflow.DoesNotExist: raise Http404("Workflow was recently deleted") ctx = JsonizeContext(request.locale_id, modules) return jsonize_clientside_init(state, ctx)
def _render_course(request, course, lesson_url_prefix): logged_in_user = None if request.user and request.user.is_authenticated: with transaction.atomic(): lock_user_by_id(request.user.id, for_write=False) logged_in_user = jsonize_clientside_user( query_clientside_user(request.user.id)) try: courses = AllCoursesByLocale[course.locale_id] except KeyError: courses = [] # We render using HTML, not React, to make this page SEO-friendly. return TemplateResponse( request, "course.html", { "initState": json.dumps({ "loggedInUser": logged_in_user, "courses": [ dict(href=course.href, title=course.title) for course in AllCoursesByLocale.get( request.locale_id, []) ], }), "course": course, "courses": courses, "lessons": list(course.lessons.values()), "lesson_url_prefix": lesson_url_prefix, }, )