def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value cls = models.Thematic discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone thematic_id = args.get('id') id_ = int(Node.from_global_id(thematic_id)[1]) thematic = cls.get(id_) permissions = get_permissions(user_id, discussion_id) allowed = thematic.user_can(user_id, CrudPermissions.UPDATE, permissions) if not allowed: raise HTTPUnauthorized() with cls.default_db.no_autoflush: # introducing history at every step, including thematics + questions # noqa: E501 thematic.copy(tombstone=True) title_entries = args.get('title_entries') if title_entries is not None and len(title_entries) == 0: raise Exception( 'Thematic titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None update_langstring_from_input_entries(thematic, 'title', title_entries) update_langstring_from_input_entries( thematic, 'description', args.get('description_entries')) kwargs = {} video = args.get('video', None) if video is not None: update_langstring_from_input_entries( thematic, 'video_title', video.get('title_entries', [])) update_langstring_from_input_entries( thematic, 'video_description_top', video.get('description_entries_top', [])) update_langstring_from_input_entries( thematic, 'video_description_bottom', video.get('description_entries_bottom', [])) update_langstring_from_input_entries( thematic, 'video_description_side', video.get('description_entries_side', [])) kwargs['video_html_code'] = video.get('html_code', None) if args.get('identifier') is not None: kwargs['identifier'] = args.get('identifier') for attr, value in kwargs.items(): setattr(thematic, attr, value) db = thematic.db # change order if needed order = args.get('order') if order: thematic.source_links[0].order = order # add uploaded image as an attachment to the idea image = args.get('image') if image is not None: if image == 'TO_DELETE' and thematic.attachments: # delete the image attachment = thematic.attachments[0] attachment.document.delete_file() db.delete(attachment.document) db.delete(attachment) thematic.attachments.remove(attachment) else: filename = os.path.basename(context.POST[image].filename) mime_type = context.POST[image].type document = models.File(discussion=discussion, mime_type=mime_type, title=filename) document.add_file_data(context.POST[image].file) # if there is already an attachment, remove it with the # associated document (image) if thematic.attachments: thematic.attachments[0].document.delete_file() db.delete(thematic.attachments[0].document) thematic.attachments.remove(thematic.attachments[0]) attachment = models.IdeaAttachment( document=document, discussion=discussion, creator_id=context.authenticated_userid, title=filename, attachmentPurpose=EMBED_ATTACHMENT) thematic.attachments.append(attachment) db.flush() questions_input = args.get('questions') existing_questions = { question.id: question for question in thematic.get_children() } updated_questions = set() if questions_input is not None: for idx, question_input in enumerate(questions_input): if question_input.get('id', None) is not None: id_ = int(Node.from_global_id(question_input['id'])[1]) updated_questions.add(id_) question = models.Question.get(id_) # archive the question question.copy(tombstone=True) update_langstring_from_input_entries( question, 'title', question_input['title_entries']) # modify question order question.source_links[0].order = idx + 1.0 else: title_ls = langstring_from_input_entries( question_input['title_entries']) question = models.Question(title=title_ls, discussion_id=discussion_id) db.add( models.IdeaLink(source=thematic, target=question, order=idx + 1.0)) # remove question (tombstone) that are not in questions_input for question_id in set(existing_questions.keys()).difference( updated_questions): existing_questions[question_id].is_tombstone = True db.flush() return UpdateThematic(thematic=thematic)
def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value cls = models.Thematic discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone permissions = get_permissions(user_id, discussion_id) allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE, permissions) if not allowed or (allowed == IF_OWNED and user_id == Everyone): raise HTTPUnauthorized() identifier = args.get('identifier') with cls.default_db.no_autoflush: title_entries = args.get('title_entries') if len(title_entries) == 0: raise Exception( 'Thematic titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None title_langstring = langstring_from_input_entries(title_entries) description_langstring = langstring_from_input_entries( args.get('description_entries')) kwargs = {} if description_langstring is not None: kwargs['description'] = description_langstring video = args.get('video') if video is not None: video_title = langstring_from_input_entries( video.get('title_entries', None)) if video_title is not None: kwargs['video_title'] = video_title video_description_top = langstring_from_input_entries( video.get('description_entries_top', None)) if video_description_top is not None: kwargs['video_description_top'] = video_description_top video_description_bottom = langstring_from_input_entries( video.get('description_entries_bottom', None)) if video_description_bottom is not None: kwargs[ 'video_description_bottom'] = video_description_bottom video_description_side = langstring_from_input_entries( video.get('description_entries_side', None)) if video_description_side is not None: kwargs['video_description_side'] = video_description_side video_html_code = video.get('html_code', None) if video_html_code is not None: kwargs['video_html_code'] = video_html_code # Our thematic, because it inherits from Idea, needs to be # associated to the root idea of the discussion. # We create a hidden root thematic, corresponding to the # `identifier` phase, child of the root idea, # and add our thematic as a child of this root thematic. root_thematic = get_root_thematic_for_phase(discussion, identifier) if root_thematic is None: root_thematic = create_root_thematic(discussion, identifier) saobj = cls(discussion_id=discussion_id, title=title_langstring, identifier=identifier, **kwargs) db = saobj.db db.add(saobj) order = len(root_thematic.get_children()) + 1.0 db.add( models.IdeaLink(source=root_thematic, target=saobj, order=args.get('order', order))) # add uploaded image as an attachment to the idea image = args.get('image') if image is not None: filename = os.path.basename(context.POST[image].filename) mime_type = context.POST[image].type document = models.File(discussion=discussion, mime_type=mime_type, title=filename) document.add_file_data(context.POST[image].file) db.add( models.IdeaAttachment( document=document, idea=saobj, discussion=discussion, creator_id=context.authenticated_userid, title=filename, attachmentPurpose=EMBED_ATTACHMENT)) db.flush() questions_input = args.get('questions') if questions_input is not None: for idx, question_input in enumerate(questions_input): title_ls = langstring_from_input_entries( question_input['title_entries']) question = models.Question(title=title_ls, discussion_id=discussion_id) db.add( models.IdeaLink(source=saobj, target=question, order=idx + 1.0)) db.flush() return CreateThematic(thematic=saobj)
def mutate(root, args, context, info): cls = models.Thematic discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid or Everyone thematic_id = args.get('id') id_ = int(Node.from_global_id(thematic_id)[1]) thematic = cls.get(id_) permissions = get_permissions(user_id, discussion_id) allowed = thematic.user_can(user_id, CrudPermissions.UPDATE, permissions) if not allowed or (allowed == IF_OWNED and user_id == Everyone): raise HTTPUnauthorized() with cls.default_db.no_autoflush: title_entries = args.get('title_entries') if len(title_entries) == 0: raise Exception( 'Thematic titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None update_langstring_from_input_entries(thematic, 'title', title_entries) update_langstring_from_input_entries( thematic, 'description', args.get('description_entries')) kwargs = {} video = args.get('video') if video is not None: update_langstring_from_input_entries(thematic, 'video_title', video['title_entries']) update_langstring_from_input_entries( thematic, 'video_description', video['description_entries']) kwargs['video_html_code'] = video['html_code'] # take the first entry and set it for short_title kwargs['short_title'] = title_entries[0]['value'] kwargs['identifier'] = args.get('identifier') for attr, value in kwargs.items(): setattr(thematic, attr, value) db = thematic.db db.flush() questions_input = args.get('questions') existing_questions = { question.id: question for question in thematic.get_children() } updated_questions = set() if questions_input is not None: for question_input in questions_input: if question_input.get('id', None) is not None: id_ = int(Node.from_global_id(question_input['id'])[1]) updated_questions.add(id_) question = models.Question.get(id_) update_langstring_from_input_entries( question, 'title', question_input['title_entries']) else: title_ls = langstring_from_input_entries( question_input['title_entries']) models.Question(title=title_ls, discussion_id=discussion_id) thematic.children.append( models.Question(title=title_ls, discussion_id=discussion_id)) # remove question (tombstone it) that are not in questions_input for question_id in set( existing_questions.keys()).difference(updated_questions): existing_questions[ question_id].tombstone_date = datetime.utcnow() db.flush() return UpdateThematic(thematic=thematic)
def mutate(root, args, context, info): cls = models.Thematic discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone permissions = get_permissions(user_id, discussion_id) allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE, permissions) if not allowed or (allowed == IF_OWNED and user_id == Everyone): raise HTTPUnauthorized() identifier = args.get('identifier') with cls.default_db.no_autoflush: title_entries = args.get('title_entries') if len(title_entries) == 0: raise Exception( 'Thematic titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None title_langstring = langstring_from_input_entries(title_entries) description_langstring = langstring_from_input_entries( args.get('description_entries')) kwargs = {} if description_langstring is not None: kwargs['description'] = description_langstring video = args.get('video') if video is not None: video_title = langstring_from_input_entries( video['title_entries']) if video_title is not None: kwargs['video_title'] = video_title video_description = langstring_from_input_entries( video['description_entries']) if video_description is not None: kwargs['video_description'] = video_description kwargs['video_html_code'] = video['html_code'] # Our thematic, because it inherits from Idea, needs to be # associated to the root idea of the discussion. # We create a hidden root thematic, corresponding to the # `identifier` phase, child of the root idea, # and add our thematic as a child of this root thematic. root_thematic = [ idea for idea in discussion.root_idea.get_children() if getattr(idea, 'identifier', '') == identifier ] if not root_thematic: short_title = u'Phase {}'.format(identifier) root_thematic = cls(discussion_id=discussion_id, short_title=short_title, title=langstring_from_input_entries([{ 'locale_code': 'en', 'value': short_title }]), identifier=identifier, hidden=True) discussion.root_idea.children.append(root_thematic) else: root_thematic = root_thematic[0] # take the first entry and set it for short_title short_title = title_entries[0]['value'] saobj = cls(discussion_id=discussion_id, title=title_langstring, short_title=short_title, identifier=identifier, **kwargs) root_thematic.children.append(saobj) db = saobj.db db.add(saobj) db.flush() questions_input = args.get('questions') if questions_input is not None: for question_input in questions_input: title_ls = langstring_from_input_entries( question_input['title_entries']) saobj.children.append( models.Question(title=title_ls, discussion_id=discussion_id)) db.flush() return CreateThematic(thematic=saobj)
def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value MEDIA_ATTACHMENT = models.AttachmentPurpose.MEDIA_ATTACHMENT.value cls = models.Idea discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone thematic_id = args.get('id') id_ = int(Node.from_global_id(thematic_id)[1]) thematic = cls.get(id_) permissions = get_permissions(user_id, discussion_id) allowed = thematic.user_can(user_id, CrudPermissions.UPDATE, permissions) if not allowed: raise HTTPUnauthorized() with cls.default_db.no_autoflush as db: # introducing history at every step, including thematics + questions # noqa: E501 thematic.copy(tombstone=True) title_entries = args.get('title_entries') if title_entries is not None and len(title_entries) == 0: raise Exception( 'Thematic titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None update_langstring_from_input_entries(thematic, 'title', title_entries) update_langstring_from_input_entries( thematic, 'description', args.get('description_entries')) kwargs = {} video = args.get('video', None) if video is not None: update_langstring_from_input_entries( thematic, 'video_title', video.get('title_entries', [])) update_langstring_from_input_entries( thematic, 'video_description_top', video.get('description_entries_top', [])) update_langstring_from_input_entries( thematic, 'video_description_bottom', video.get('description_entries_bottom', [])) update_langstring_from_input_entries( thematic, 'video_description_side', video.get('description_entries_side', [])) kwargs['video_html_code'] = video.get('html_code', None) video_media = video.get('media_file', None) if video_media: update_attachment(discussion, models.IdeaAttachment, video_media, thematic.attachments, MEDIA_ATTACHMENT, db, context) kwargs['message_view_override'] = args.get('message_view_override') for attr, value in kwargs.items(): setattr(thematic, attr, value) # change order if needed order = args.get('order') if order: thematic.source_links[0].order = order # add uploaded image as an attachment to the idea image = args.get('image') if image is not None: update_attachment(discussion, models.IdeaAttachment, image, thematic.attachments, EMBED_ATTACHMENT, db, context) # Create the idea announcement object which corresponds to the instructions announcement = args.get('announcement') if announcement is not None: announcement_title_entries = announcement.get('title_entries') if len(announcement_title_entries) == 0: raise Exception( 'Announcement titleEntries needs at least one entry') announcement_title_langstring = langstring_from_input_entries( announcement_title_entries) announcement_body_langstring = langstring_from_input_entries( announcement.get('body_entries', None)) saobj2 = create_idea_announcement( user_id, discussion, thematic, announcement_title_langstring, announcement_body_langstring) db.add(saobj2) questions_input = args.get('questions') existing_questions = { question.id: question for question in thematic.get_children() } updated_questions = set() if questions_input is not None: for idx, question_input in enumerate(questions_input): if question_input.get('id', None) is not None: id_ = int(Node.from_global_id(question_input['id'])[1]) updated_questions.add(id_) question = models.Question.get(id_) # archive the question question.copy(tombstone=True) update_langstring_from_input_entries( question, 'title', question_input['title_entries']) # modify question order question.source_links[0].order = idx + 1.0 else: title_ls = langstring_from_input_entries( question_input['title_entries']) question = models.Question(title=title_ls, discussion_id=discussion_id) db.add( models.IdeaLink(source=thematic, target=question, order=idx + 1.0)) # remove question (tombstone) that are not in questions_input for question_id in set(existing_questions.keys()).difference( updated_questions): existing_questions[question_id].is_tombstone = True db.flush() return UpdateThematic(thematic=thematic)
def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value MEDIA_ATTACHMENT = models.AttachmentPurpose.MEDIA_ATTACHMENT.value cls = models.Idea phase_identifier = args.get('identifier') if phase_identifier == Phases.survey.value: cls = models.Thematic discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone permissions = get_permissions(user_id, discussion_id) allowed = cls.user_can_cls(user_id, CrudPermissions.CREATE, permissions) if not allowed or (allowed == IF_OWNED and user_id == Everyone): raise HTTPUnauthorized() with cls.default_db.no_autoflush as db: title_entries = args.get('title_entries') if len(title_entries) == 0: raise Exception( 'Thematic titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None title_langstring = langstring_from_input_entries(title_entries) description_langstring = langstring_from_input_entries( args.get('description_entries')) kwargs = {} if description_langstring is not None: kwargs['description'] = description_langstring kwargs['message_view_override'] = args.get('message_view_override') video = args.get('video') video_media = None if video is not None: video_title = langstring_from_input_entries( video.get('title_entries', None)) if video_title is not None: kwargs['video_title'] = video_title video_description_top = langstring_from_input_entries( video.get('description_entries_top', None)) if video_description_top is not None: kwargs['video_description_top'] = video_description_top video_description_bottom = langstring_from_input_entries( video.get('description_entries_bottom', None)) if video_description_bottom is not None: kwargs[ 'video_description_bottom'] = video_description_bottom video_description_side = langstring_from_input_entries( video.get('description_entries_side', None)) if video_description_side is not None: kwargs['video_description_side'] = video_description_side video_html_code = video.get('html_code', None) if video_html_code is not None: kwargs['video_html_code'] = video_html_code video_media = video.get('media_file', None) parent_idea_id = args.get('parent_id') if parent_idea_id: parent_idea_id = int(Node.from_global_id(parent_idea_id)[1]) parent_idea = models.Idea.get(parent_idea_id) if not parent_idea: raise Exception('Parent Idea not found') if parent_idea.discussion != discussion: # No cross-debate references are allowed, # for security reasons raise Exception( 'Parent Idea does not belong to this discussion' ) # noqa: E501 else: if phase_identifier in (Phases.thread.value, Phases.multiColumns.value): parent_idea = discussion.root_idea else: # Our thematic, because it inherits from Idea, needs to be # associated to the root idea of the discussion. # We create a hidden root thematic, corresponding to the # `identifier` phase, child of the root idea, # and add our thematic as a child of this root thematic. parent_idea = get_root_thematic_for_phase( discussion, phase_identifier) if parent_idea is None: parent_idea = create_root_thematic( discussion, phase_identifier) saobj = cls(discussion_id=discussion_id, title=title_langstring, **kwargs) if cls == models.Thematic: saobj.identifier = phase_identifier # I don't think this is really used db.add(saobj) order = len(parent_idea.get_children()) + 1.0 db.add( models.IdeaLink(source=parent_idea, target=saobj, order=args.get('order', order))) # Create the idea announcement object which corresponds to the instructions announcement = args.get('announcement') if announcement is not None: announcement_title_entries = announcement.get('title_entries') if len(announcement_title_entries) == 0: raise Exception( 'Announcement titleEntries needs at least one entry') announcement_title_langstring = langstring_from_input_entries( announcement_title_entries) announcement_body_langstring = langstring_from_input_entries( announcement.get('body_entries', None)) saobj2 = create_idea_announcement( user_id, discussion, saobj, announcement_title_langstring, announcement_body_langstring) db.add(saobj2) # add uploaded image as an attachment to the idea image = args.get('image') if image is not None: new_attachment = create_attachment(discussion, models.IdeaAttachment, image, EMBED_ATTACHMENT, context) new_attachment.idea = saobj db.add(new_attachment) # add uploaded image as an attachment to the idea if video_media is not None: new_attachment = create_attachment(discussion, models.IdeaAttachment, video_media, MEDIA_ATTACHMENT, context) new_attachment.idea = saobj db.add(new_attachment) questions_input = args.get('questions') if questions_input is not None: for idx, question_input in enumerate(questions_input): title_ls = langstring_from_input_entries( question_input['title_entries']) question = models.Question(title=title_ls, discussion_id=discussion_id) db.add( models.IdeaLink(source=saobj, target=question, order=idx + 1.0)) db.flush() return CreateThematic(thematic=saobj)