def serialize_node_for_page_list(content: Content, context: Context): if content.type==ContentType.Page: if not content.parent: folder = None else: folder = Context(CTX.DEFAULT).toDict(content.parent) result = DictLikeClass( id = content.content_id, label = content.label, status = context.toDict(content.get_status()), folder = folder ) return result if content.type==ContentType.File: result = DictLikeClass( id = content.content_id, label = content.label if content.label else content.file_name, status = context.toDict(content.get_status()), folder = Context(CTX.DEFAULT).toDict(content.parent) ) return result # TODO - DA - 2014-10-16 - THE FOLLOWING CODE SHOULD BE REMOVED # # if content.type==ContentType.Folder: # return DictLikeClass( # id = content.content_id, # label = content.label, # ) raise NotImplementedError('node type / context not implemented: {} {}'. format(content.type, context.context_string))
def update_file_data(self, item: Content, new_filename: str, new_mimetype: str, new_file_content) -> Content: item.owner = self._user item.file_name = new_filename item.file_mimetype = new_mimetype item.file_content = new_file_content item.revision_type = ActionDescription.REVISION return item
def serialize_node_for_page_list(content: Content, context: Context): if content.type==ContentType.Page: if not content.parent: folder = None else: folder = Context(CTX.DEFAULT).toDict(content.parent) result = DictLikeClass( id = content.content_id, label = content.label, status = context.toDict(content.get_status()), folder = folder ) return result if content.type==ContentType.File: result = DictLikeClass( id = content.content_id, label = content.label, status = context.toDict(content.get_status()), folder = Context(CTX.DEFAULT).toDict(content.parent) ) return result # TODO - DA - 2014-10-16 - THE FOLLOWING CODE SHOULD BE REMOVED # # if content.type==ContentType.Folder: # return DictLikeClass( # id = content.content_id, # label = content.label, # ) raise NotImplementedError('node type / context not implemented: {} {}'. format(content.type, context.context_string))
def compare_content_for_sorting_by_type_and_name(content1: Content, content2: Content): """ :param content1: :param content2: :return: 1 if content1 > content2 -1 if content1 < content2 0 if content1 = content2 """ if content1.type==content2.type: if content1.get_label().lower()>content2.get_label().lower(): return 1 elif content1.get_label().lower()<content2.get_label().lower(): return -1 return 0 else: # TODO - D.A. - 2014-12-02 - Manage Content Types Dynamically content_type_order = [ContentType.Folder, ContentType.Page, ContentType.Thread, ContentType.File] result = content_type_order.index(content1.type)-content_type_order.index(content2.type) if result<0: return -1 elif result>0: return 1 else: return 0
def create(self, content_type: str, workspace: Workspace, parent: Content = None, label: str = '', do_save=False, is_temporary: bool = False) -> Content: assert content_type in ContentType.allowed_types() if content_type == ContentType.Folder and not label: label = self.generate_folder_label(workspace, parent) content = Content() content.owner = self._user content.parent = parent content.workspace = workspace content.type = content_type content.label = label content.is_temporary = is_temporary content.revision_type = ActionDescription.CREATION if content.type in ( ContentType.Page, ContentType.Thread, ): content.file_extension = '.html' if do_save: DBSession.add(content) self.save(content, ActionDescription.CREATION) return content
def compare_content_for_sorting_by_type_and_name(content1: Content, content2: Content): """ :param content1: :param content2: :return: 1 if content1 > content2 -1 if content1 < content2 0 if content1 = content2 """ if content1.type == content2.type: if content1.get_label().lower() > content2.get_label().lower(): return 1 elif content1.get_label().lower() < content2.get_label().lower(): return -1 return 0 else: # TODO - D.A. - 2014-12-02 - Manage Content Types Dynamically content_type_order = [ ContentType.Folder, ContentType.Page, ContentType.Thread, ContentType.File ] result = content_type_order.index( content1.type) - content_type_order.index(content2.type) if result < 0: return -1 elif result > 0: return 1 else: return 0
def serialize_content_for_general_list(content: Content, context: Context): content_type = ContentType(content.type) last_activity_date = content.get_last_activity_date() last_activity_date_formatted = format_datetime(last_activity_date, locale=tg.i18n.get_lang()[0]) last_activity_label = format_timedelta( datetime.utcnow() - last_activity_date, locale=tg.i18n.get_lang()[0], ) last_activity_label = last_activity_label.replace(' ', '\u00A0') # espace insécable return DictLikeClass( id=content.content_id, folder = DictLikeClass({'id': content.parent_id}) if content.parent else None, workspace=context.toDict(content.workspace) if content.workspace else None, label=content.get_label(), url=ContentType.fill_url(content), type=DictLikeClass(content_type.toDict()), status=context.toDict(content.get_status()), is_deleted=content.is_deleted, is_archived=content.is_archived, is_editable=content.is_editable, last_activity = DictLikeClass({'date': last_activity_date, 'label': last_activity_date_formatted, 'delta': last_activity_label}) )
def test_serializer_content__menui_api_context__children(self): folder_without_child = Content() folder_without_child.type = ContentType.Folder res = Context(CTX.MENU_API).toDict(folder_without_child) eq_(False, res['children']) folder_with_child = Content() folder_with_child.type = ContentType.Folder folder_without_child.parent = folder_with_child DBSession.add(folder_with_child) DBSession.add(folder_without_child) DBSession.flush() res = Context(CTX.MENU_API).toDict(folder_with_child) eq_(True, res['children']) for curtype in ContentType.all(): if curtype not in (ContentType.Folder, ContentType.Comment): item = Content() item.type = curtype fake_child = Content() fake_child.type = curtype fake_child.parent = item DBSession.add(item) DBSession.add(fake_child) DBSession.flush() res = Context(CTX.MENU_API).toDict(item) eq_(False, res['children'])
def set_status(self, content: Content, new_status: str): if new_status in ContentStatus.allowed_values(): content.status = new_status content.revision_type = ActionDescription.STATUS_UPDATE else: raise ValueError( 'The given value {} is not allowed'.format(new_status))
def update_content(self, item: Content, new_label: str, new_content: str=None) -> Content: if item.label==new_label and item.description==new_content: raise SameValueError(_('The content did not changed')) item.owner = self._user item.label = new_label item.description = new_content if new_content else item.description # TODO: convert urls into links item.revision_type = ActionDescription.EDITION return item
def serialize_node_for_page(content: Content, context: Context): if content.type in (ContentType.Page, ContentType.File) : data_container = content # The following properties are overriden by revision values if content.revision_to_serialize>0: for revision in content.revisions: if revision.revision_id==content.revision_to_serialize: data_container = revision break result = DictLikeClass( id=content.content_id, parent=context.toDict(content.parent), workspace=context.toDict(content.workspace), type=content.type, is_new=content.has_new_information_for(context.get_user()), content=data_container.description, created=data_container.created, updated=content.last_revision.updated, label=data_container.label, icon=ContentType.get_icon(content.type), owner=context.toDict(content.first_revision.owner), last_modification_author=context.toDict(content.last_revision.owner), status=context.toDict(data_container.get_status()), links=[], revision_nb = len(content.revisions), selected_revision='latest' if content.revision_to_serialize<=0 else content.revision_to_serialize, history=Context(CTX.CONTENT_HISTORY).toDict(content.get_history()), is_editable=content.is_editable, is_deleted=content.is_deleted, is_archived=content.is_archived, urls = context.toDict({ 'mark_read': context.url(Content.format_path('/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_read', content)), 'mark_unread': context.url(Content.format_path('/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_unread', content)) }) ) if content.type == ContentType.File: depot = DepotManager.get() depot_stored_file = depot.get(data_container.depot_file) result.label = content.label result['file'] = DictLikeClass( name=data_container.file_name, size=depot_stored_file.content_length, mimetype=data_container.file_mimetype) return result if content.type==ContentType.Folder: value = DictLikeClass( id=content.content_id, label=content.label, is_new=content.has_new_information_for(context.get_user()), ) return value raise NotImplementedError
def serialize_content_for_workspace_and_folder(content: Content, context: Context): thread_nb_all = content.get_child_nb(ContentType.Thread) thread_nb_open = content.get_child_nb(ContentType.Thread) file_nb_all = content.get_child_nb(ContentType.File) file_nb_open = content.get_child_nb(ContentType.File) folder_nb_all = content.get_child_nb(ContentType.Folder) folder_nb_open = content.get_child_nb(ContentType.Folder) page_nb_all = content.get_child_nb(ContentType.Page) page_nb_open = content.get_child_nb(ContentType.Page) content_nb_all = thread_nb_all +\ thread_nb_open +\ file_nb_all +\ file_nb_open +\ folder_nb_all +\ folder_nb_open +\ page_nb_all +\ page_nb_open result = None if content.type == ContentType.Folder: allowed_content = DictLikeClass(content.properties['allowed_content']), result = DictLikeClass(id=content.content_id, label=content.label, created=content.created, workspace=context.toDict(content.workspace), allowed_content=DictLikeClass( content.properties['allowed_content']), allowed_content_types=context.toDict( content.get_allowed_content_types()), selected_revision='latest', status=context.toDict(content.get_status()), owner=context.toDict(content.owner), thread_nb=DictLikeClass(all=thread_nb_all, open=thread_nb_open), file_nb=DictLikeClass(all=file_nb_all, open=file_nb_open), folder_nb=DictLikeClass(all=folder_nb_all, open=folder_nb_open), page_nb=DictLikeClass(all=page_nb_all, open=page_nb_open), content_nb=DictLikeClass(all=content_nb_all)) elif content.type == ContentType.Page: result = DictLikeClass( id=content.content_id, label=content.label, created=content.created, workspace=context.toDict(content.workspace), owner=DictLikeClass(id=content.owner.user_id, name=content.owner.get_display_name()), status=DictLikeClass(id='', label=''), #FIXME - EXPORT DATA ) return result
def create(self, content_type: str, workspace: Workspace, parent: Content=None, label:str ='', do_save=False, is_temporary: bool=False) -> Content: assert content_type in ContentType.allowed_types() if content_type == ContentType.Folder and not label: label = self.generate_folder_label(workspace, parent) content = Content() content.owner = self._user content.parent = parent content.workspace = workspace content.type = content_type content.label = label content.is_temporary = is_temporary content.revision_type = ActionDescription.CREATION if content.type in ( ContentType.Page, ContentType.Thread, ): content.file_extension = '.html' if do_save: DBSession.add(content) self.save(content, ActionDescription.CREATION) return content
def update_file_data(self, item: Content, new_filename: str, new_mimetype: str, new_content: bytes) -> Content: item.owner = self._user item.file_name = new_filename item.file_mimetype = new_mimetype item.depot_file = FileIntent( new_content, new_filename, new_mimetype, ) item.revision_type = ActionDescription.REVISION return item
def new_revision(content: Content) -> Content: """ Prepare context to update a Content. It will add a new updatable revision to the content. :param content: Content instance to update :return: """ with DBSession.no_autoflush: try: if inspect(content.revision).has_identity: content.new_revision() RevisionsIntegrity.add_to_updatable(content.revision) yield content finally: RevisionsIntegrity.remove_from_updatable(content.revision)
def serialize_node_for_thread_list(content: Content, context: Context): if content.type == ContentType.Thread: return DictLikeClass(id=content.content_id, url=ContentType.fill_url(content), label=content.get_label(), status=context.toDict(content.get_status()), folder=context.toDict(content.parent), workspace=context.toDict(content.workspace) if content.workspace else None, comment_nb=len(content.get_comments())) if content.type == ContentType.Folder: return Context(CTX.DEFAULT).toDict(content) raise NotImplementedError
def move(self, item: Content, new_parent: Content, must_stay_in_same_workspace:bool=True, new_workspace:Workspace=None): if must_stay_in_same_workspace: if new_parent and new_parent.workspace_id != item.workspace_id: raise ValueError('the item should stay in the same workspace') item.parent = new_parent if new_parent: item.workspace = new_parent.workspace elif new_workspace: item.workspace = new_workspace item.revision_type = ActionDescription.MOVE
def serialize_node_for_thread_list(content: Content, context: Context): if content.type==ContentType.Thread: return DictLikeClass( id = content.content_id, url=ContentType.fill_url(content), label=content.get_label(), status=context.toDict(content.get_status()), folder=context.toDict(content.parent), workspace=context.toDict(content.workspace) if content.workspace else None, comment_nb=len(content.get_comments()) ) if content.type==ContentType.Folder: return Context(CTX.DEFAULT).toDict(content) raise NotImplementedError
def serialize_node_for_page(item: Content, context: Context): if item.type == ContentType.Thread: return DictLikeClass( content=item.description, created=item.created, icon=ContentType.get_icon(item.type), id=item.content_id, label=item.label, links=[], owner=context.toDict(item.owner), parent=context.toDict(item.parent), selected_revision='latest', status=context.toDict(item.get_status()), type=item.type, workspace=context.toDict(item.workspace), comments=reversed(context.toDict(item.get_comments())), is_new=item.has_new_information_for(context.get_user()), history=Context(CTX.CONTENT_HISTORY).toDict(item.get_history()), urls=context.toDict({ 'mark_read': context.url( Content.format_path( '/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_read', item)), 'mark_unread': context.url( Content.format_path( '/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_unread', item)) }), ) if item.type == ContentType.Comment: return DictLikeClass( is_new=item.has_new_information_for(context.get_user()), content=item.description, created=item.created, created_as_delta=item.created_as_delta(), icon=ContentType.get_icon(item.type), id=item.content_id, label=item.label, owner=context.toDict(item.owner), # REMOVE parent = context.toDict(item.parent), type=item.type, urls=context.toDict({ 'delete': context.url( '/workspaces/{wid}/folders/{fid}/{ctype}/{cid}/comments/{commentid}/put_delete' .format(wid=item.workspace_id, fid=item.parent.parent_id, ctype=item.parent.type + 's', cid=item.parent.content_id, commentid=item.content_id)) })) if item.type == ContentType.Folder: return Context(CTX.DEFAULT).toDict(item)
def serialize_content_for_workspace(content: Content, context: Context): thread_nb_all = content.get_child_nb(ContentType.Thread) thread_nb_open = content.get_child_nb(ContentType.Thread) file_nb_all = content.get_child_nb(ContentType.File) file_nb_open = content.get_child_nb(ContentType.File) folder_nb_all = content.get_child_nb(ContentType.Folder) folder_nb_open = content.get_child_nb(ContentType.Folder) page_nb_all = content.get_child_nb(ContentType.Page) page_nb_open = content.get_child_nb(ContentType.Page) content_nb_all = thread_nb_all +\ thread_nb_open +\ file_nb_all +\ file_nb_open +\ folder_nb_all +\ folder_nb_open +\ page_nb_all +\ page_nb_open result = None if content.type==ContentType.Folder: result = DictLikeClass( id = content.content_id, label = content.label, thread_nb = DictLikeClass( all = thread_nb_all, open = thread_nb_open, ), file_nb = DictLikeClass( all = file_nb_all, open = file_nb_open, ), folder_nb = DictLikeClass( all = folder_nb_all, open = folder_nb_open, ), page_nb = DictLikeClass( all = page_nb_all, open = page_nb_open, ), content_nb = DictLikeClass(all = content_nb_all), is_editable=content.is_editable, ) return result
def create_comment(self, workspace: Workspace=None, parent: Content=None, content:str ='', do_save=False) -> Content: assert parent and parent.type!=ContentType.Folder item = Content() item.owner = self._user item.parent = parent item.workspace = workspace item.type = ContentType.Comment item.description = content item.label = '' item.revision_type = ActionDescription.COMMENT if do_save: self.save(item, ActionDescription.COMMENT) return item
def serialize_content_for_workspace(content: Content, context: Context): thread_nb_all = content.get_child_nb(ContentType.Thread) thread_nb_open = content.get_child_nb(ContentType.Thread) file_nb_all = content.get_child_nb(ContentType.File) file_nb_open = content.get_child_nb(ContentType.File) folder_nb_all = content.get_child_nb(ContentType.Folder) folder_nb_open = content.get_child_nb(ContentType.Folder) page_nb_all = content.get_child_nb(ContentType.Page) page_nb_open = content.get_child_nb(ContentType.Page) content_nb_all = thread_nb_all +\ thread_nb_open +\ file_nb_all +\ file_nb_open +\ folder_nb_all +\ folder_nb_open +\ page_nb_all +\ page_nb_open result = None if content.type==ContentType.Folder: result = DictLikeClass( id = content.content_id, label = content.label, thread_nb = DictLikeClass( all = thread_nb_all, open = thread_nb_open, ), file_nb = DictLikeClass( all = file_nb_all, open = file_nb_open, ), folder_nb = DictLikeClass( all = folder_nb_all, open = folder_nb_open, ), page_nb = DictLikeClass( all = page_nb_all, open = page_nb_open, ), content_nb = DictLikeClass(all = content_nb_all) ) return result
def serialize_content_for_menu_api(content: Content, context: Context): content_id = content.content_id workspace_id = content.workspace_id has_children = False if content.type == ContentType.Folder: has_children = content.get_child_nb(ContentType.Any) > 0 result = DictLikeClass( id = CST.TREEVIEW_MENU.ID_TEMPLATE__FULL.format(workspace_id, content_id), children = has_children, text = content.get_label(), a_attr = { 'href' : context.url(ContentType.fill_url(content))}, li_attr = { 'title': content.get_label(), 'class': 'tracim-tree-item-is-a-folder' }, type = content.type, state = { 'opened': True if ContentType.Folder!=content.type else False, 'selected': False } ) return result
def serialize_item(content: Content, context: Context): if ContentType.Comment==content.type: content = content.parent result = DictLikeClass( id = content.content_id, label = content.label if content.label else content.file_name, icon = ContentType.get_icon(content.type), status = context.toDict(content.get_status()), folder = context.toDict(DictLikeClass(id = content.parent.content_id if content.parent else None)), workspace = context.toDict(content.workspace), is_deleted = content.is_deleted, is_archived = content.is_archived, url = context.url('/workspaces/{wid}/folders/{fid}/{ctype}/{cid}'.format(wid = content.workspace_id, fid=content.parent_id, ctype=content.type+'s', cid=content.content_id)), last_action = context.toDict(content.get_last_action()) ) return result
def serialize_item(content: Content, context: Context): if ContentType.Comment==content.type: content = content.parent result = DictLikeClass( id = content.content_id, label = content.label, icon = ContentType.get_icon(content.type), status = context.toDict(content.get_status()), folder = context.toDict(DictLikeClass(id = content.parent.content_id if content.parent else None)), workspace = context.toDict(content.workspace), is_deleted = content.is_deleted, is_archived = content.is_archived, url = context.url('/workspaces/{wid}/folders/{fid}/{ctype}/{cid}'.format(wid = content.workspace_id, fid=content.parent_id, ctype=content.type+'s', cid=content.content_id)), last_action = context.toDict(content.get_last_action()) ) return result
def test_sort_by_label_or_filename(self): c1 = Content() c1.label = 'ABCD' c1.type = 'file' c2 = Content() c2.label = '' c2.type = 'file' c2.file_name = 'AABC' c3 = Content() c3.label = 'BCDE' c3.type = 'file' items = [c1, c2, c3] sorteds = ContentApi.sort_content(items) eq_(sorteds[0], c2) eq_(sorteds[1], c1) eq_(sorteds[2], c3)
def validate_new_content(self, content: Content) -> bool: """ :param content: Content with label to test :return: True if content label is not in conflict with existing resource """ return self.content_label_is_free( content_label_as_file=content.get_label_as_file(), workspace=content.workspace, parent=content.parent, exclude_content_id=content.content_id, )
def test_serialize_Content_DEFAULT(self): self.app.get('/_test_vars') # Allow to create fake context obj = Content() obj.content_id = 132 obj.label = 'Some label' obj.description = 'Some Description' res = Context(CTX.DEFAULT).toDict(obj) eq_(res.__class__, DictLikeClass, res) eq_(obj.content_id, res.id, res) eq_(obj.label, res.label, res) ok_('folder' in res.keys()) ok_('id' in res.folder.keys()) eq_(None, res.folder.id) eq_(1, len(res.folder.keys())) ok_('workspace' in res.keys()) eq_(None, res.workspace, res) eq_(4, len(res.keys()), res)
def test_compare_content_for_sorting_by_label(self): c1 = Content() c1.label = 'bbb' c1.type = 'file' c2 = Content() c2.label = 'aaa' c2.type = 'file' c11 = c1 eq_(1, compare_content_for_sorting_by_type_and_name(c1, c2)) eq_(-1, compare_content_for_sorting_by_type_and_name(c2, c1)) eq_(0, compare_content_for_sorting_by_type_and_name(c1, c11))
def serialize_content_for_workspace_and_folder(content: Content, context: Context): thread_nb_all = content.get_child_nb(ContentType.Thread) thread_nb_open = content.get_child_nb(ContentType.Thread) file_nb_all = content.get_child_nb(ContentType.File) file_nb_open = content.get_child_nb(ContentType.File) folder_nb_all = content.get_child_nb(ContentType.Folder) folder_nb_open = content.get_child_nb(ContentType.Folder) page_nb_all = content.get_child_nb(ContentType.Page) page_nb_open = content.get_child_nb(ContentType.Page) content_nb_all = thread_nb_all +\ thread_nb_open +\ file_nb_all +\ file_nb_open +\ folder_nb_all +\ folder_nb_open +\ page_nb_all +\ page_nb_open result = None if content.type==ContentType.Folder: allowed_content = DictLikeClass(content.properties['allowed_content']), result = DictLikeClass( id=content.content_id, label=content.label, created=content.created, workspace=context.toDict(content.workspace), allowed_content=DictLikeClass(content.properties['allowed_content']), allowed_content_types=context.toDict(content.get_allowed_content_types()), selected_revision='latest', status=context.toDict(content.get_status()), owner=context.toDict(content.owner), thread_nb=DictLikeClass(all=thread_nb_all, open=thread_nb_open), file_nb=DictLikeClass(all=file_nb_all, open=file_nb_open), folder_nb=DictLikeClass(all=folder_nb_all, open=folder_nb_open), page_nb=DictLikeClass(all=page_nb_all, open=page_nb_open), content_nb=DictLikeClass(all = content_nb_all) ) elif content.type==ContentType.Page: result = DictLikeClass( id = content.content_id, label = content.label, created = content.created, workspace = context.toDict(content.workspace), owner = DictLikeClass( id = content.owner.user_id, name = content.owner.get_display_name() ), status = DictLikeClass(id='', label=''), #FIXME - EXPORT DATA ) return result
def serialize_node_for_thread(item: Content, context: Context): if item.type in (ContentType.Thread, ContentType.Task, ContentType.Ticket): return DictLikeClass( content = item.description, created = item.created, updated = item.last_revision.updated, revision_nb = len(item.revisions), icon = ContentType.get_icon(item.type), id = item.content_id, label = item.label, links=[], owner = context.toDict(item.owner), last_modification_author=context.toDict(item.last_revision.owner), parent = context.toDict(item.parent), selected_revision = 'latest', status = context.toDict(item.get_status()), type = item.type, workspace = context.toDict(item.workspace), comments = reversed(context.toDict(item.get_comments())), is_new=item.has_new_information_for(context.get_user()), history = Context(CTX.CONTENT_HISTORY).toDict(item.get_history()), is_editable=item.is_editable, is_deleted=item.is_deleted, is_archived=item.is_archived, urls = context.toDict({ 'mark_read': context.url(Content.format_path('/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_read', item)), 'mark_unread': context.url(Content.format_path('/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_unread', item)) }), ) if item.type == ContentType.Comment: return DictLikeClass( is_new=item.has_new_information_for(context.get_user()), content = item.description, created = item.created, created_as_delta = item.created_as_delta(), icon = ContentType.get_icon(item.type), id = item.content_id, label = item.label, owner = context.toDict(item.owner), # REMOVE parent = context.toDict(item.parent), type = item.type, urls = context.toDict({ 'delete': context.url('/workspaces/{wid}/folders/{fid}/{ctype}/{cid}/comments/{commentid}/put_delete'.format(wid = item.workspace_id, fid=item.parent.parent_id, ctype=item.parent.type+'s', cid=item.parent.content_id, commentid=item.content_id)) }) ) if item.type==ContentType.Folder: return Context(CTX.DEFAULT).toDict(item)
def mark_read(self, content: Content, read_datetime: datetime = None, do_flush: bool = True, recursive: bool = True) -> Content: assert self._user assert content # The algorithm is: # 1. define the read datetime # 2. update all revisions related to current Content # 3. do the same for all child revisions # (ie parent_id is content_id of current content) if not read_datetime: read_datetime = datetime.datetime.now() viewed_revisions = DBSession.query(ContentRevisionRO) \ .filter(ContentRevisionRO.content_id==content.content_id).all() for revision in viewed_revisions: revision.read_by[self._user] = read_datetime if recursive: # mark read : # - all children # - parent stuff (if you mark a comment as read, # then you have seen the parent) # - parent comments for child in content.get_valid_children(): self.mark_read(child, read_datetime=read_datetime, do_flush=False) if ContentType.Comment == content.type: self.mark_read(content.parent, read_datetime=read_datetime, do_flush=False, recursive=False) for comment in content.parent.get_comments(): if comment != content: self.mark_read(comment, read_datetime=read_datetime, do_flush=False, recursive=False) if do_flush: self.flush() return content
def populate_content_with_event( self, content: Content, event: iCalendarEvent, event_name: str, ) -> None: """ Populate Content content instance from iCalendarEvent event attributes. :param content: content to populate :param event: event with data to insert in content :param event_name: Event name (ID) like 20160602T083511Z-18100-1001-1-71_Bastien-20160602T083516Z.ics :return: given content """ content.label = event.get('summary') content.description = event.get('description') content.properties = { 'name': event_name, 'location': event.get('location'), 'raw': event.to_ical().decode("utf-8"), 'start': event.get('dtend').dt.strftime('%Y-%m-%d %H:%M:%S%z'), 'end': event.get('dtstart').dt.strftime('%Y-%m-%d %H:%M:%S%z'), }
def set_allowed_content(self, folder: Content, allowed_content_dict:dict): """ :param folder: the given folder instance :param allowed_content_dict: must be something like this: dict( folder = True thread = True, file = False, page = True ) :return: """ properties = dict(allowed_content = allowed_content_dict) folder.properties = properties
def set_allowed_content(self, folder: Content, allowed_content_dict: dict): """ :param folder: the given folder instance :param allowed_content_dict: must be something like this: dict( folder = True thread = True, file = False, page = True ) :return: """ properties = dict(allowed_content=allowed_content_dict) folder.properties = properties
def create(self, content_type: str, workspace: Workspace, parent: Content = None, label: str = '', is_temporary: bool = False, do_save=False) -> Content: assert content_type in ContentType.allowed_types() content = Content() content.owner = self._user content.parent = parent content.workspace = workspace content.type = content_type content.label = label content.is_temporary = is_temporary content.revision_type = ActionDescription.CREATION if do_save: DBSession.add(content) self.save(content, ActionDescription.CREATION) return content
def create(self, content_type: str, workspace: Workspace, parent: Content=None, label:str ='', do_save=False) -> Content: assert content_type in ContentType.allowed_types() content = Content() content.owner = self._user content.parent = parent content.workspace = workspace content.type = content_type content.label = label content.revision_type = ActionDescription.CREATION if do_save: DBSession.add(content) self.save(content, ActionDescription.CREATION) return content
def mark_unread(self, content: Content, do_flush=True) -> Content: assert self._user assert content revisions = DBSession.query(ContentRevisionRO) \ .filter(ContentRevisionRO.content_id==content.content_id).all() for revision in revisions: del revision.read_by[self._user] for child in content.get_valid_children(): self.mark_unread(child, do_flush=False) if do_flush: self.flush() return content
def mark_read(self, content: Content, read_datetime: datetime=None, do_flush: bool=True, recursive: bool=True) -> Content: assert self._user assert content # The algorithm is: # 1. define the read datetime # 2. update all revisions related to current Content # 3. do the same for all child revisions # (ie parent_id is content_id of current content) if not read_datetime: read_datetime = datetime.datetime.now() viewed_revisions = DBSession.query(ContentRevisionRO) \ .filter(ContentRevisionRO.content_id==content.content_id).all() for revision in viewed_revisions: revision.read_by[self._user] = read_datetime if recursive: # mark read : # - all children # - parent stuff (if you mark a comment as read, # then you have seen the parent) # - parent comments for child in content.get_valid_children(): self.mark_read(child, read_datetime=read_datetime, do_flush=False) if ContentType.Comment == content.type: self.mark_read(content.parent, read_datetime=read_datetime, do_flush=False, recursive=False) for comment in content.parent.get_comments(): if comment != content: self.mark_read(comment, read_datetime=read_datetime, do_flush=False, recursive=False) if do_flush: self.flush() return content
def test_sort_by_content_type(self): c1 = Content() c1.label = 'AAAA' c1.type = 'file' c2 = Content() c2.label = 'BBBB' c2.type = 'folder' items = [c1, c2] sorteds = ContentApi.sort_content(items) eq_( sorteds[0], c2, 'value is {} instead of {}'.format(sorteds[0].content_id, c2.content_id)) eq_( sorteds[1], c1, 'value is {} instead of {}'.format(sorteds[1].content_id, c1.content_id))
def serialize_node_for_page(content: Content, context: Context): if content.type in (ContentType.Page, ContentType.File) : data_container = content # The following properties are overriden by revision values if content.revision_to_serialize>0: for revision in content.revisions: if revision.revision_id==content.revision_to_serialize: data_container = revision break result = DictLikeClass( id=content.content_id, parent=context.toDict(content.parent), workspace=context.toDict(content.workspace), type=content.type, is_new=content.has_new_information_for(context.get_user()), content=data_container.description, created=data_container.created, label=data_container.label, icon=ContentType.get_icon(content.type), owner=context.toDict(data_container.owner), status=context.toDict(data_container.get_status()), links=context.toDict(content.extract_links_from_content(data_container.description)), revisions=context.toDict(sorted(content.revisions, key=lambda v: v.created, reverse=True)), selected_revision='latest' if content.revision_to_serialize<=0 else content.revision_to_serialize, history=Context(CTX.CONTENT_HISTORY).toDict(content.get_history()), urls = context.toDict({ 'mark_read': context.url(Content.format_path('/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_read', content)), 'mark_unread': context.url(Content.format_path('/workspaces/{wid}/folders/{fid}/{ctype}s/{cid}/put_unread', content)) }) ) if content.type==ContentType.File: result.label = content.label if content.label else content.file_name result['file'] = DictLikeClass( name = data_container.file_name, size = len(data_container.file_content), mimetype = data_container.file_mimetype) return result if content.type==ContentType.Folder: value = DictLikeClass( id=content.content_id, label=content.label, is_new=content.has_new_information_for(context.get_user()), ) return value raise NotImplementedError
def save(self, content: Content, action_description: str = None, do_flush=True, do_notify=True): """ Save an object, flush the session and set the revision_type property :param content: :param action_description: :return: """ assert action_description is None or action_description in ActionDescription.allowed_values( ) if not action_description: # See if the last action has been modified if content.revision_type == None or len( get_history(content.revision, 'revision_type')) <= 0: # The action has not been modified, so we set it to default edition action_description = ActionDescription.EDITION if action_description: content.revision_type = action_description if do_flush: # INFO - 2015-09-03 - D.A. # There are 2 flush because of the use # of triggers for content creation # # (when creating a content, actually this is an insert of a new # revision in content_revisions ; so the mark_read operation need # to get full real data from database before to be prepared. DBSession.add(content) DBSession.flush() # TODO - 2015-09-03 - D.A. - Do not use triggers # We should create a new ContentRevisionRO object instead of Content # This would help managing view/not viewed status self.mark_read(content, do_flush=True) if do_notify: self.do_notify(content)
def save(self, content: Content, action_description: str=None, do_flush=True, do_notify=True): """ Save an object, flush the session and set the revision_type property :param content: :param action_description: :return: """ assert action_description is None or action_description in ActionDescription.allowed_values() if not action_description: # See if the last action has been modified if content.revision_type==None or len(get_history(content.revision, 'revision_type'))<=0: # The action has not been modified, so we set it to default edition action_description = ActionDescription.EDITION if action_description: content.revision_type = action_description if do_flush: # INFO - 2015-09-03 - D.A. # There are 2 flush because of the use # of triggers for content creation # # (when creating a content, actually this is an insert of a new # revision in content_revisions ; so the mark_read operation need # to get full real data from database before to be prepared. DBSession.add(content) DBSession.flush() # TODO - 2015-09-03 - D.A. - Do not use triggers # We should create a new ContentRevisionRO object instead of Content # This would help managing view/not viewed status self.mark_read(content, do_flush=True) if do_notify: self.do_notify(content)
def test_sort_by_content_type(self): c1 = Content() c1.label = 'AAAA' c1.type = 'file' c2 = Content() c2.label = 'BBBB' c2.type = 'folder' items = [c1, c2] sorteds = ContentApi.sort_content(items) eq_(sorteds[0], c2, 'value is {} instead of {}'.format(sorteds[0].content_id, c2.content_id)) eq_(sorteds[1], c1, 'value is {} instead of {}'.format(sorteds[1].content_id, c1.content_id))
def undelete(self, content: Content): content.owner = self._user content.is_deleted = False content.revision_type = ActionDescription.UNDELETION
def delete(self, content: Content): content.owner = self._user content.is_deleted = True content.revision_type = ActionDescription.DELETION