def do_clone_workflow(user, workflow: models.Workflow) -> models.Workflow: """Clone a workflow. :param user: User performing the operation :param workflow: source workflow :return: Cloned object """ new_workflow = models.Workflow( user=workflow.user, name=create_new_name( workflow.name, models.Workflow.objects.filter( Q(user=workflow.user) | Q(shared=workflow.user)), ), description_text=workflow.description_text, nrows=workflow.nrows, ncols=workflow.ncols, attributes=copy.deepcopy(workflow.attributes), query_builder_ops=copy.deepcopy(workflow.query_builder_ops), luser_email_column_md5=workflow.luser_email_column_md5, lusers_is_outdated=workflow.lusers_is_outdated) new_workflow.save() try: new_workflow.shared.set(list(workflow.shared.all())) new_workflow.lusers.set(list(workflow.lusers.all())) # Clone the columns for item_obj in workflow.columns.all(): do_clone_column_only(item_obj, new_workflow=new_workflow) # Update the luser_email_column if needed: if workflow.luser_email_column: new_workflow.luser_email_column = new_workflow.columns.get( name=workflow.luser_email_column.name, ) # Clone the DB table sql.clone_table(workflow.get_data_frame_table_name(), new_workflow.get_data_frame_table_name()) # Clone actions for item_obj in workflow.actions.all(): do_clone_action(user, item_obj, new_workflow) for item_obj in workflow.views.all(): do_clone_view(user, item_obj, new_workflow) # Done! new_workflow.save() except Exception as exc: raise OnTaskServiceException( message=_('Error while cloning workflow: {0}').format(exc), to_delete=[new_workflow]) workflow.log(user, models.Log.WORKFLOW_CLONE, id_old=workflow.id, name_old=workflow.name) return new_workflow
def view_clone( request: HttpRequest, pk: Optional[int] = None, workflow: Optional[Workflow] = None, view: Optional[View] = None, ) -> JsonResponse: """Clone a view. :param request: HTTP request :param pk: ID of the view to clone. The workflow is taken from the session :return: AJAX response """ if request.method == 'GET': return JsonResponse({ 'html_form': render_to_string('table/includes/partial_view_clone.html', { 'pk': pk, 'vname': view.name }, request=request), }) id_old = view.id name_old = view.name view = do_clone_view(view, new_workflow=None, new_name=create_new_name(view.name, workflow.views)) view.log(request.user, Log.VIEW_CLONE, id_old=id_old, name_old=name_old) return JsonResponse({'html_redirect': ''})
def clone_column(user, column: models.Column) -> models.Column: """Create a clone of a column. :param user: User executing operation :param column: Object to clone :return: Cloned object (DF has an additional column as well """ workflow = column.workflow new_column = do_clone_column_only(column, new_name=create_new_name( column.name, workflow.columns)) # Update the number of columns in the workflow workflow.ncols += 1 workflow.save() workflow.refresh_from_db() # Reposition the new column at the end new_column.position = workflow.ncols new_column.save() # Create the column in the database sql.add_column_to_db(workflow.get_data_frame_table_name(), new_column.name, new_column.data_type) sql.copy_column_in_db(workflow.get_data_frame_table_name(), column.name, new_column.name) new_column.log(user, models.Log.COLUMN_CLONE) return new_column
def clone_action( request: http.HttpRequest, pk: int, workflow: Optional[models.Workflow] = None, action: Optional[models.Action] = None, ) -> http.JsonResponse: """View to clone an action. :param request: Request object :param pk: id of the action to clone :param workflow: Workflow being manipulated (set by decorator) :param action: Action being cloned (set by decorator) :return: """ if request.method == 'GET': return http.JsonResponse({ 'html_form': render_to_string('action/includes/partial_action_clone.html', { 'pk': pk, 'name': action.name }, request=request), }) services.do_clone_action(request.user, action, new_workflow=None, new_name=create_new_name(action.name, workflow.actions)) messages.success(request, _('Action successfully cloned.')) return http.JsonResponse({'html_redirect': ''})
def view_clone( request: http.HttpRequest, pk: Optional[int] = None, workflow: Optional[models.Workflow] = None, view: Optional[models.View] = None, ) -> http.JsonResponse: """Clone a view. :param request: HTTP request :param pk: ID of the view to clone. The workflow is taken from the session :param workflow: Workflow being processed :param view: View to be cloned. :return: AJAX response """ if request.method == 'GET': return http.JsonResponse({ 'html_form': render_to_string('table/includes/partial_view_clone.html', { 'pk': pk, 'vname': view.name }, request=request) }) try: services.do_clone_view(request.user, view, new_workflow=None, new_name=create_new_name( view.name, workflow.views)) except OnTaskServiceException as exc: exc.message_to_error(request) exc.delete() return http.JsonResponse({'html_redirect': ''})
def _do_clone( request: HttpRequest, conn: Type[Connection], mgr, clone_url: str, ) -> JsonResponse: """Finish AJAX handshake to clone a connection. :param request: HTTP request :param pk: ID of the connection to clone. :return: AJAX response """ if request.method == 'GET': return JsonResponse({ 'html_form': render_to_string('dataops/includes/partial_connection_clone.html', { 'pk': conn.id, 'cname': conn.name, 'clone_url': clone_url }, request=request) }) # Proceed to clone the connection id_old = conn.id name_old = conn.name conn.id = None conn.name = create_new_name(conn.name, mgr) conn.save() conn.log(request.user, conn.clone_event, id_old=id_old, name_old=name_old) return JsonResponse({'html_redirect': ''})
def clone_wf_column(column: Column) -> Column: """Create a clone of a column. :param column: Object to clone :return: Cloned object (DF has an additional column as well """ workflow = column.workflow new_column = do_clone_column_only(column, new_name=create_new_name( column.name, workflow.columns)) # Update the number of columns in the workflow workflow.ncols += 1 workflow.save() workflow.refresh_from_db() # Reposition the new column at the end new_column.position = workflow.ncols new_column.save() # Create the column in the database add_column_to_db(workflow.get_data_frame_table_name(), new_column.name, new_column.data_type) copy_column_in_db(workflow.get_data_frame_table_name(), column.name, new_column.name) return new_column
def clone_connection( request: http.HttpRequest, conn: models.Connection, mgr, clone_url: str, ) -> http.JsonResponse: """Finish AJAX handshake to clone a connection. :param request: HTTP request :param conn: Connection to clone. :param mgr: Manager to handle the right type of connection :param clone_url: String with the URL to perform the clone operation. :return: AJAX response """ if request.method == 'GET': return http.JsonResponse({ 'html_form': render_to_string('connection/includes/partial_clone.html', { 'pk': conn.id, 'cname': conn.name, 'clone_url': clone_url }, request=request) }) # Proceed to clone the connection id_old = conn.id name_old = conn.name conn.id = None conn.name = create_new_name(conn.name, mgr) conn.save() conn.log(request.user, conn.clone_event, id_old=id_old, name_old=name_old) return http.JsonResponse({'html_redirect': ''})
def _do_clone_workflow(workflow: Workflow) -> Workflow: """Clone the workflow. :param workflow: source workflow :return: Clone object """ new_workflow = Workflow( user=workflow.user, name=create_new_name( workflow.name, Workflow.objects.filter( Q(user=workflow.user) | Q(shared=workflow.user)), ), description_text=workflow.description_text, nrows=workflow.nrows, ncols=workflow.ncols, attributes=copy.deepcopy(workflow.attributes), query_builder_ops=copy.deepcopy(workflow.query_builder_ops), luser_email_column_md5=workflow.luser_email_column_md5, lusers_is_outdated=workflow.lusers_is_outdated) new_workflow.save() try: new_workflow.shared.set(list(workflow.shared.all())) new_workflow.lusers.set(list(workflow.lusers.all())) # Clone the columns for item_obj in workflow.columns.all(): do_clone_column_only(item_obj, new_workflow=new_workflow) # Update the luser_email_column if needed: if workflow.luser_email_column: new_workflow.luser_email_column = new_workflow.columns.get( name=workflow.luser_email_column.name, ) # Clone the DB table clone_table(workflow.get_data_frame_table_name(), new_workflow.get_data_frame_table_name()) # Clone actions for item_obj in workflow.actions.all(): do_clone_action(item_obj, new_workflow) for item_obj in workflow.views.all(): do_clone_view(item_obj, new_workflow) # Done! new_workflow.save() except Exception as exc: new_workflow.delete() raise exc return new_workflow
def sqlconn_clone(request: HttpRequest, pk: int) -> JsonResponse: """AJAX handshake to clone a SQL connection. :param request: HTTP request :param pk: ID of the connection to clone. :return: AJAX response """ context = {'pk': pk} # For rendering # Get the connection conn = SQLConnection.objects.filter(pk=pk).first() if not conn: # The view is not there. Redirect to workflow detail return JsonResponse({'html_redirect': reverse('home')}) # Get the name of the connection to clone context['cname'] = conn.name if request.method == 'GET': return JsonResponse({ 'html_form': render_to_string( 'dataops/includes/partial_sqlconn_clone.html', context, request=request), }) # POST REQUEST # Proceed to clone the connection conn.id = None conn.name = create_new_name(conn.name, SQLConnection.objects) conn.save() # Log the event Log.objects.register( request.user, Log.SQL_CONNECTION_CLONE, None, { 'name': conn.name, 'description': conn.description_txt, 'conn_type': conn.conn_type, 'conn_driver': conn.conn_driver, 'db_user': conn.db_user, 'db_passwd': _('<PROTECTED>') if conn.db_password else '', 'db_host': conn.db_host, 'db_port': conn.db_port, 'db_name': conn.db_name, 'db_table': conn.db_table}) return JsonResponse({'html_redirect': ''})
def clone_condition( request: HttpRequest, pk: int, workflow: Optional[Workflow] = None, condition: Optional[Condition] = None, action_pk: Optional[int] = None, ) -> JsonResponse: """JSON request to clone a condition. The post request must come with the action_content :param request: Request object :param pk: id of the condition to clone :param action_pk: Primary key of the action to receive the condition :return: JSON response """ if action_pk: action = Action.objects.filter(id=action_pk).first() if not action: messages.error(request, _('Incorrect action id.')) return JsonResponse({'html_redirect': ''}) else: action = condition.action # If the request has the 'action_content', update the action action_content = request.POST.get('action_content') if action_content: condition.action.set_text_content(action_content) condition.action.save() log_context = { 'id_old': condition.id, 'name_old': condition.name} condition = do_clone_condition( condition, new_action=action, new_name=create_new_name(condition.name, action.conditions)) # Log event log_context['id_new'] = condition.id log_context['name_new'] = condition.name Log.objects.register( request.user, Log.CONDITION_CLONE, condition.action.workflow, log_context) messages.success(request, _('Condition successfully cloned.')) # Refresh the page to show the column in the list. return JsonResponse({'html_redirect': ''})
def clone_action( request: HttpRequest, pk: int, workflow: Optional[Workflow] = None, action: Optional[Action] = None, ) -> JsonResponse: """View to clone an action. :param request: Request object :param pk: id of the action to clone :return: """ if request.method == 'GET': return JsonResponse({ 'html_form': render_to_string('action/includes/partial_action_clone.html', { 'pk': pk, 'name': action.name }, request=request), }) # POST REQUEST! log_payload = { 'id_old': action.id, 'name_old': action.name, } action = do_clone_action(action, new_workflow=None, new_name=create_new_name(action.name, workflow.actions)) # Log event log_payload['id_new'] = action.id log_payload['name_new'] = action.name Log.objects.register( request.user, Log.ACTION_CLONE, workflow, log_payload, ) messages.success(request, _('Action successfully cloned.')) return JsonResponse({'html_redirect': ''})
def clone_condition( request: http.HttpRequest, pk: int, workflow: Optional[models.Workflow] = None, condition: Optional[models.Condition] = None, action_pk: Optional[int] = None, ) -> http.JsonResponse: """JSON request to clone a condition. The post request must come with the action_content :param request: Request object :param pk: id of the condition to clone :param workflow: Workflow being manipulated (set by decorator) :param condition: Condition being cloned (set by decorator) :param action_pk: Primary key of the action to receive the condition :return: JSON response """ del pk, workflow if action_pk: action = models.Action.objects.filter(id=action_pk).first() if not action: messages.error(request, _('Incorrect action id.')) return http.JsonResponse({'html_redirect': ''}) else: action = condition.action # If the request has the 'action_content', update the action action_content = request.POST.get('action_content') if action_content: condition.action.set_text_content(action_content) condition.action.save() condition = services.do_clone_condition(request.user, condition, new_action=action, new_name=create_new_name( condition.name, action.conditions)) messages.success(request, _('Condition successfully cloned.')) return http.JsonResponse({'html_redirect': ''})
def view_clone( request: HttpRequest, pk: Optional[int] = None, workflow: Optional[Workflow] = None, view: Optional[View] = None, ) -> JsonResponse: """Clone a view. :param request: HTTP request :param pk: ID of the view to clone. The workflow is taken from the session :return: AJAX response """ if request.method == 'GET': return JsonResponse({ 'html_form': render_to_string('table/includes/partial_view_clone.html', { 'pk': pk, 'vname': view.name }, request=request), }) # POST REQUEST old_name = view.name view = do_clone_view(view, new_workflow=None, new_name=create_new_name(view.name, workflow.views)) # Proceed to clone the view # Log the event Log.objects.register( request.user, Log.VIEW_CLONE, workflow, { 'id': workflow.id, 'name': workflow.name, 'old_view_name': old_name, 'new_view_name': view.name }) return JsonResponse({'html_redirect': ''})