def make_init_state(request, workflow=None, modules=None): """Build a dict to embed as JSON in `window.initState` in HTML.""" ret = {} if workflow: ret['workflowId'] = workflow.id ret['workflow'] = WorkflowSerializer(workflow, context={'request': request}).data wf_modules = workflow.wf_modules \ .prefetch_related('parameter_vals__parameter_spec', 'module_version') wf_module_data_list = WfModuleSerializer(wf_modules, many=True).data ret['wfModules'] = dict([(str(wfm['id']), wfm) for wfm in wf_module_data_list]) ret['selected_wf_module'] = workflow.selected_wf_module del ret['workflow']['selected_wf_module'] if modules: modules_data_list = ModuleSerializer(modules, many=True).data ret['modules'] = dict([(str(m['id']), m) for m in modules_data_list]) if request.user.is_authenticated(): ret['loggedInUser'] = UserSerializer(request.user).data if workflow and not workflow.request_read_only(request): ret['updateTableModuleIds'] = load_update_table_module_ids() return ret
def get_workflow_as_delta_and_needs_render(self): """ Return (apply-delta dict, needs_render), or raise Workflow.DoesNotExist needs_render is a (workflow_id, delta_id) pair. """ with Workflow.authorized_lookup_and_cooperative_lock( 'read', self.scope['user'], self.scope['session'], pk=self.workflow_id) as workflow: request = RequestWrapper(self.scope['user'], self.scope['session']) ret = { 'updateWorkflow': (WorkflowSerializer(workflow, context={ 'request': request }).data), } tabs = list(workflow.live_tabs) ret['updateTabs'] = dict( (tab.slug, TabSerializer(tab).data) for tab in tabs) wf_modules = list(WfModule.live_in_workflow(workflow.id)) ret['updateWfModules'] = dict( (str(wfm.id), WfModuleSerializer(wfm).data) for wfm in wf_modules) if workflow.are_all_render_results_fresh(): needs_render = None else: needs_render = (workflow.id, workflow.last_delta_id) return (ret, needs_render)
def make_init_state(request, workflow=None, modules=None): """Build a dict to embed as JSON in `window.initState` in HTML.""" ret = {} if workflow: ret['workflowId'] = workflow.id ret['workflow'] = WorkflowSerializer(workflow, context={'request': request}).data wf_modules = workflow.wf_modules \ .prefetch_related('parameter_vals__parameter_spec', 'module_version') wf_module_data_list = WfModuleSerializer(wf_modules, many=True).data ret['wfModules'] = dict([(str(wfm['id']), wfm) for wfm in wf_module_data_list]) ret['selected_wf_module'] = workflow.selected_wf_module ret['uploadConfig'] = { 'bucket': minio.UserFilesBucket, 'accessKey': settings.MINIO_ACCESS_KEY, # never _SECRET_KEY 'server': settings.MINIO_EXTERNAL_URL } ret['user_files_bucket'] = minio.UserFilesBucket del ret['workflow']['selected_wf_module'] if modules: modules_data_list = ModuleSerializer(modules, many=True).data ret['modules'] = dict([(str(m['id']), m) for m in modules_data_list]) if request.user.is_authenticated(): ret['loggedInUser'] = UserSerializer(request.user).data if workflow and not workflow.request_read_only(request): ret['updateTableModuleIds'] = load_update_table_module_ids() return ret
def workflow_detail(request, pk, format=None): try: workflow = Workflow.objects.get(pk=pk) except Workflow.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if not workflow.user_authorized(request.user): return HttpResponseForbidden() if request.method == 'GET': serializer = WorkflowSerializer(workflow) return Response(serializer.data) # We use PATCH to set the order of the modules when the user drags. elif request.method == 'PATCH': try: ReorderModulesCommand.create(workflow, request.data) except ValueError as e: # Caused by bad id or order keys not in range 0..n-1 (though they don't need to be sorted) return Response({'message': str(e), 'status_code':400}, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_204_NO_CONTENT) elif request.method == 'POST': try: ChangeWorkflowTitleCommand.create(workflow, request.data['newName']) except Exception as e: return Response({'message': str(e), 'status_code':400}, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_204_NO_CONTENT) elif request.method == 'DELETE': workflow.delete() return Response(status=status.HTTP_204_NO_CONTENT)
def workflow_list(request, format=None): if request.method == 'GET': workflows = Workflow.objects.filter(owner=request.user) serializer = WorkflowSerializerLite(workflows, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = WorkflowSerializer(data=request.data) if serializer.is_valid(): serializer.save(owner=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
async def ws_notify(self): """ Notify WebSocket clients that we just undid or redid. This default implementation sends a 'delta' command. It will always include a 'set-workflow' property; it may include a 'set-wf-module' command and may include a 'clear-wf-module' command. """ data = {} with self.workflow.cooperative_lock(): workflow_data = WorkflowSerializer(self.workflow).data # Remove the data we didn't generate correctly because we had no # HTTP request. del workflow_data['is_anonymous'] del workflow_data['owner_name'] del workflow_data['read_only'] data['updateWorkflow'] = _prepare_json(workflow_data) data['updateWfModules'] = {} if hasattr(self, '_changed_wf_module_versions'): for id, delta_id in self._changed_wf_module_versions.items(): data['updateWfModules'][str(id)] = { 'last_relevant_delta_id': delta_id, 'error_msg': '', # Tell clients this WfModule is "busy". Don't actually # _set_ the busy flag: the busy flag is set exclusively # by "fetch" (`module_dispatch_event`) and we can't # override that safely. We don't need another busy flag # for renders: this transient status is enough. 'status': 'busy', 'quick_fixes': [], 'output_columns': None } if hasattr(self, 'wf_module'): self.wf_module.refresh_from_db() if self.wf_module.workflow_id: wf_module_data = WfModuleSerializer(self.wf_module).data wf_module_data['status'] = 'busy' # rationale above data['updateWfModules'][str(self.wf_module_id)] = \ _prepare_json(wf_module_data) else: # When we did or undid this command, we removed the # WfModule from the Workflow. data['clearWfModuleIds'] = [self.wf_module_id] await websockets.ws_client_send_delta_async(self.workflow_id, data)
def make_init_state(request, workflow=None, modules=None): """ Build a dict to embed as JSON in `window.initState` in HTML. Raise Http404 if the workflow disappeared. """ ret = {} if workflow: try: with workflow.cooperative_lock(): # raise DoesNotExist on race ret['workflowId'] = workflow.id ret['workflow'] = WorkflowSerializer(workflow, context={ 'request': request }).data tabs = list(workflow.live_tabs) ret['tabs'] = dict( (str(tab.slug), TabSerializer(tab).data) for tab in tabs) wf_modules = list(WfModule.live_in_workflow(workflow)) ret['wfModules'] = { str(wfm.id): WfModuleSerializer(wfm).data for wfm in wf_modules } except Workflow.DoesNotExist: raise Http404('Workflow was recently deleted') ret['uploadConfig'] = { 'bucket': minio.UserFilesBucket, 'accessKey': settings.MINIO_ACCESS_KEY, # never _SECRET_KEY 'server': settings.MINIO_EXTERNAL_URL } ret['user_files_bucket'] = minio.UserFilesBucket if modules: modules_data_list = ModuleSerializer(modules, many=True).data ret['modules'] = dict([(str(m['id_name']), m) for m in modules_data_list]) if request.user.is_authenticated: ret['loggedInUser'] = UserSerializer(request.user).data return ret
def make_init_state(request, workflow=None, modules=None): ret = {} if workflow: ret['workflowId'] = workflow.id ret['workflow'] = WorkflowSerializer(workflow, context={'user' : request.user}).data ret['selected_wf_module'] = workflow.selected_wf_module if modules: ret['modules'] = ModuleSerializer(modules, many=True).data if request.user.is_authenticated(): ret['loggedInUser'] = UserSerializer(request.user).data ret['editCellsModuleId'] = edit_cells_module_id() ret['sortModuleId'] = sort_module_id() ret['reorderModuleId'] = reorder_module_id() return ret
def make_init_state(request, workflow=None, modules=None): """ 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. """ ret = {} if workflow: try: with workflow.cooperative_lock(): # raise DoesNotExist on race ret['workflowId'] = workflow.id ret['workflow'] = WorkflowSerializer(workflow, context={ 'request': request }).data tabs = list(workflow.live_tabs) ret['tabs'] = dict( (str(tab.slug), TabSerializer(tab).data) for tab in tabs) wf_modules = list(WfModule.live_in_workflow(workflow)) ret['wfModules'] = { str(wfm.id): WfModuleSerializer(wfm).data for wfm in wf_modules } workflow.last_viewed_at = timezone.now() workflow.save(update_fields=['last_viewed_at']) except Workflow.DoesNotExist: raise Http404('Workflow was recently deleted') if modules: modules_data_list = ModuleSerializer(modules, many=True).data ret['modules'] = dict([(str(m['id_name']), m) for m in modules_data_list]) if request.user.is_authenticated: ret['loggedInUser'] = UserSerializer(request.user).data return ret
def workflow_list(request, format=None): if request.method == 'GET': workflows = Workflow.objects.filter(Q(owner=request.user)) # turn queryset into array so we can sort it ourselves by reverse chron workflows = workflows.all() workflows = sorted(workflows, key=lambda wf: wf.last_update(), reverse=True) serializer = WorkflowSerializerLite(workflows, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = WorkflowSerializer(data=request.data, context={'user': request.user}) if serializer.is_valid(): serializer.save(owner=request.user) log_user_event(request.user, 'Create Workflow') return Response(serializer.data, status=status.HTTP_201_CREATED) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def ws_notify(self): """ Notify WebSocket clients that we just undid or redid. This default implementation sends a 'delta' command. It will always include a 'set-workflow' property; it may include a 'set-wf-module' command and may include a 'clear-wf-module' command. """ data = {} with self.workflow.cooperative_lock(): workflow_data = WorkflowSerializer(self.workflow).data # Remove the data we didn't generate correctly because we had no # HTTP request. del workflow_data['is_anonymous'] del workflow_data['owner_name'] del workflow_data['read_only'] data['updateWorkflow'] = _prepare_json(workflow_data) data['updateWfModules'] = {} if hasattr(self, '_changed_wf_module_versions'): for id, delta_id in self._changed_wf_module_versions.items(): data['updateWfModules'][str(id)] = { 'last_relevant_delta_id': delta_id, 'error_msg': '', 'output_columns': None } if hasattr(self, 'wf_module'): self.wf_module.refresh_from_db() if self.wf_module.workflow_id: wf_module_data = WfModuleSerializer(self.wf_module).data data['updateWfModules'][str(self.wf_module_id)] = \ _prepare_json(wf_module_data) else: # When we did or undid this command, we removed the # WfModule from the Workflow. data['clearWfModuleIds'] = [self.wf_module_id] websockets.ws_client_send_delta_sync(self.workflow_id, data)
def workflow_detail(request, pk, format=None): workflow = get_object_or_404(Workflow, pk=pk) if not workflow.user_authorized_read(request.user): return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': if workflow.name.startswith('Demo'): log_user_event(request.user, 'Opened Demo Workflow', {'name': workflow.name}) with workflow.cooperative_lock(): serializer = WorkflowSerializer(workflow, context={'user' : request.user}) return Response(serializer.data) # We use PATCH to set the order of the modules when the user drags. elif request.method == 'PATCH': if not workflow.user_authorized_write(request.user): return HttpResponseForbidden() try: ReorderModulesCommand.create(workflow, request.data) except ValueError as e: # Caused by bad id or order keys not in range 0..n-1 (though they don't need to be sorted) return Response({'message': str(e), 'status_code':400}, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_204_NO_CONTENT) elif request.method == 'POST': if not workflow.user_authorized_write(request.user): return HttpResponseForbidden() try: if not set(request.data.keys()).intersection({"newName", "public", "module_library_collapsed", "selected_wf_module"}): raise ValueError('Unknown fields: {}'.format(request.data)) with workflow.cooperative_lock(): if 'newName' in request.data: ChangeWorkflowTitleCommand.create(workflow, request.data['newName']) if 'public' in request.data: # TODO this should be a command, so it's undoable workflow.public = request.data['public'] workflow.save() if 'module_library_collapsed' in request.data: workflow.module_library_collapsed = request.data['module_library_collapsed'] workflow.save() if 'selected_wf_module' in request.data: workflow.selected_wf_module = request.data['selected_wf_module'] workflow.save() except Exception as e: return Response({'message': str(e), 'status_code':400}, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_204_NO_CONTENT) elif request.method == 'DELETE': if not workflow.user_authorized_write(request.user): return HttpResponseForbidden() workflow.delete() return Response(status=status.HTTP_204_NO_CONTENT)
def workflow_detail(request, pk, format=None): try: workflow = Workflow.objects.get(pk=pk) except Workflow.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if not workflow.user_authorized_read(request.user): return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'GET': serializer = WorkflowSerializer(workflow, context={'user': request.user}) return Response(serializer.data) # We use PATCH to set the order of the modules when the user drags. elif request.method == 'PATCH': if not workflow.user_authorized_write(request.user): return HttpResponseForbidden() try: ReorderModulesCommand.create(workflow, request.data) except ValueError as e: # Caused by bad id or order keys not in range 0..n-1 (though they don't need to be sorted) return Response({ 'message': str(e), 'status_code': 400 }, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_204_NO_CONTENT) elif request.method == 'POST': if not workflow.user_authorized_write(request.user): return HttpResponseForbidden() try: if not set(request.data.keys()).intersection({"newName", "public" }): raise ValueError('Unknown fields: {}'.format(request.data)) if 'newName' in request.data: ChangeWorkflowTitleCommand.create(workflow, request.data['newName']) if 'public' in request.data: workflow.public = request.data['public'] workflow.save() except Exception as e: return Response({ 'message': str(e), 'status_code': 400 }, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_204_NO_CONTENT) elif request.method == 'DELETE': if not workflow.user_authorized_write(request.user): return HttpResponseForbidden() workflow.delete() return Response(status=status.HTTP_204_NO_CONTENT)