def get_all_types(self) -> [ContentType]: labels = ContentType.all() content_types = [] for label in labels: content_types.append(ContentType(label)) return ContentType.sorted(content_types)
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 serialize_it(): nonlocal content if content.type == ContentType.Comment: logger.info( 'serialize_content_for_search_result', 'Serializing parent class {} instead of {} [content #{}]'. format(content.parent.type, content.type, content.content_id)) content = content.parent data_container = content if content.revision_to_serialize > 0: for revision in content.revisions: if revision.revision_id == content.revision_to_serialize: data_container = revision break # FIXME - D.A. - 2015-02-23 - This import should not be there... from tracim.lib.content import ContentApi breadcrumbs = ContentApi(None).build_breadcrumb( data_container.workspace, data_container.content_id, skip_root=True) last_comment_datetime = data_container.updated comments = data_container.get_comments() if comments: last_comment_datetime = max( last_comment_datetime, max(comment.updated for comment in comments)) content_type = ContentType(content.type) result = DictLikeClass( id=content.content_id, type=DictLikeClass(content_type.toDict()), parent=context.toDict(content.parent), workspace=context.toDict(content.workspace), content=data_container.description, content_raw=data_container.description_as_raw_text(), created=data_container.created, created_as_delta=data_container.created_as_delta(), label=data_container.label, icon=ContentType.get_icon(content.type), owner=context.toDict(data_container.owner), status=context.toDict(data_container.get_status()), breadcrumb=context.toDict(breadcrumbs), last_activity=last_comment_datetime, last_activity_as_delta=content.datetime_as_delta( last_comment_datetime)) if content.type == ContentType.File: result.label = content.label.__str__() if not result.label or '' == result.label: result.label = 'No title' return result
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_it(): nonlocal content if content.type == ContentType.Comment: logger.info('serialize_content_for_search_result', 'Serializing parent class {} instead of {} [content #{}]'.format(content.parent.type, content.type, content.content_id)) content = content.parent data_container = content if content.revision_to_serialize>0: for revision in content.revisions: if revision.revision_id==content.revision_to_serialize: data_container = revision break # FIXME - D.A. - 2015-02-23 - This import should not be there... from tracim.lib.content import ContentApi breadcrumbs = ContentApi(None).build_breadcrumb(data_container.workspace, data_container.content_id, skip_root=True) last_comment_datetime = data_container.updated comments = data_container.get_comments() if comments: last_comment_datetime = max(last_comment_datetime, max(comment.updated for comment in comments)) content_type = ContentType(content.type) result = DictLikeClass( id = content.content_id, type = DictLikeClass(content_type.toDict()), parent = context.toDict(content.parent), workspace = context.toDict(content.workspace), content = data_container.description, content_raw = data_container.description_as_raw_text(), created = data_container.created, created_as_delta = data_container.created_as_delta(), label = data_container.label, icon = ContentType.get_icon(content.type), owner = context.toDict(data_container.owner), status = context.toDict(data_container.get_status()), breadcrumb = context.toDict(breadcrumbs), last_activity=last_comment_datetime, last_activity_as_delta=content.datetime_as_delta(last_comment_datetime) ) if content.type==ContentType.File: result.label = content.label.__str__() if content.label else content.file_name.__str__() if not result.label or ''==result.label: result.label = 'No title' 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 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 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 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 get_child_folders(self, parent: Content=None, workspace: Workspace=None, filter_by_allowed_content_types: list=[], removed_item_ids: list=[], allowed_node_types=None) -> [Content]: """ This method returns child items (folders or items) for left bar treeview. :param parent: :param workspace: :param filter_by_allowed_content_types: :param removed_item_ids: :param allowed_node_types: This parameter allow to hide folders for which the given type of content is not allowed. For example, if you want to move a Page from a folder to another, you should show only folders that accept pages :return: """ if not allowed_node_types: allowed_node_types = [ContentType.Folder] elif allowed_node_types==ContentType.Any: allowed_node_types = ContentType.all() parent_id = parent.content_id if parent else None folders = self._base_query(workspace).\ filter(Content.parent_id==parent_id).\ filter(Content.type.in_(allowed_node_types)).\ filter(Content.content_id.notin_(removed_item_ids)).\ all() if not filter_by_allowed_content_types or \ len(filter_by_allowed_content_types)<=0: # Standard case for the left treeview: we want to show all contents # in the left treeview... so we still filter because for example # comments must not appear in the treeview return [folder for folder in folders \ if folder.type in ContentType.allowed_types_for_folding()] # Now this is a case of Folders only (used for moving content) # When moving a content, you must get only folders that allow to be filled # with the type of content you want to move result = [] for folder in folders: for allowed_content_type in filter_by_allowed_content_types: if folder.type==ContentType.Folder and folder.properties['allowed_content'][allowed_content_type]==True: result.append(folder) break return result
def treeview_root(self, id='#', current_id=None, all_workspaces=True, folder_allowed_content_types='', ignore_id=None, ignore_workspace_id=None): all_workspaces = bool(int(all_workspaces)) # ignore_workspace_id is a string like 3,12,78,15 ignored_ids = [int(id) for id in ignore_workspace_id.split(',')] if ignore_workspace_id else None if not current_id: # Default case is to return list of workspaces api = WorkspaceApi(tmpl_context.current_user) workspaces = api.get_all_for_user(tmpl_context.current_user, ignored_ids) dictified_workspaces = Context(CTX.MENU_API).toDict(workspaces, 'd') return dictified_workspaces allowed_content_types = ContentType.allowed_types_from_str(folder_allowed_content_types) ignored_item_ids = [int(ignore_id)] if ignore_id else [] # Now complex case: we must return a structured tree # including the selected node, all parents (and their siblings) workspace, content = convert_id_into_instances(current_id) # The following step allow to select the parent folder when content itself is not visible in the treeview if content and content.type!=ContentType.Folder and CFG.CST.TREEVIEW_ALL!=CFG.get_instance().WEBSITE_TREEVIEW_CONTENT: content = content.parent if content.parent else None # This is the init of the recursive-like build of the tree content_parent = content tree_items = [] # The first step allow to load child of selected item # (for example, when you select a folder in the windows explorer, # then the selected folder is expanded by default) content_api = ContentApi(tmpl_context.current_user) child_folders = content_api.get_child_folders(content_parent, workspace, allowed_content_types, ignored_item_ids) if len(child_folders)>0: first_child = child_folders[0] content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, first_child, tree_items, False, allowed_content_types, ignored_item_ids) content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, content_parent, tree_items, True, allowed_content_types, ignored_item_ids) while content_parent: # Do the same for the parent level content_parent, tree_items = self._build_sibling_list_of_tree_items(workspace, content_parent, tree_items) # Now, we have a tree_items list that is the root folders list, # so we now have to put it as a child of a list of workspaces should_select_workspace = not content full_tree = self._build_sibling_list_of_workspaces(workspace, tree_items, should_select_workspace, all_workspaces) return Context(CTX.MENU_API_BUILD_FROM_TREE_ITEM).toDict(full_tree, 'd')
def serialize_node_tree_item_for_menu_api_tree(item: NodeTreeItem, context: Context): if isinstance(item.node, Content): ContentType.fill_url(item.node) return DictLikeClass( id=CST.TREEVIEW_MENU.ID_TEMPLATE__FULL.format( item.node.workspace_id, item.node.content_id), children=True if ContentType.Folder == item.node.type and len(item.children) <= 0 else context.toDict(item.children), text=item.node.get_label(), a_attr={'href': context.url(ContentType.fill_url(item.node))}, li_attr={'title': item.node.get_label()}, # type='folder', type=item.node.type, state={ 'opened': True if ContentType.Folder == item.node.type and len(item.children) > 0 else False, 'selected': item.is_selected }) elif isinstance(item.node, Workspace): return DictLikeClass( id=CST.TREEVIEW_MENU.ID_TEMPLATE__WORKSPACE_ONLY.format( item.node.workspace_id), children=True if len(item.children) <= 0 else context.toDict(item.children), text=item.node.label, a_attr={ 'href': context.url(ContentType.fill_url_for_workspace(item.node)) }, li_attr={'title': item.node.get_label()}, type='workspace', state={ 'opened': True if len(item.children) > 0 else False, 'selected': item.is_selected })
def build_breadcrumb(self, workspace, item_id=None, skip_root=False) -> [BreadcrumbItem]: """ TODO - Remove this and factorize it with other get_breadcrumb_xxx methods :param item_id: an item id (item may be normal content or folder :return: """ workspace_id = workspace.workspace_id breadcrumb = [] if not skip_root: breadcrumb.append(BreadcrumbItem(ContentType.get_icon(ContentType.FAKE_Dashboard), _('Workspaces'), tg.url('/workspaces'))) breadcrumb.append(BreadcrumbItem(ContentType.get_icon(ContentType.FAKE_Workspace), workspace.label, tg.url('/workspaces/{}'.format(workspace.workspace_id)))) if item_id: breadcrumb_folder_items = [] current_item = self.get_one(item_id, ContentType.Any, workspace) is_active = True if current_item.type==ContentType.Folder: next_url = tg.url('/workspaces/{}/folders/{}'.format(workspace_id, current_item.content_id)) else: next_url = tg.url('/workspaces/{}/folders/{}/{}s/{}'.format(workspace_id, current_item.parent_id, current_item.type, current_item.content_id)) while current_item: breadcrumb_item = BreadcrumbItem(ContentType.get_icon(current_item.type), current_item.label, next_url, is_active) is_active = False # the first item is True, then all other are False => in the breadcrumb, only the last item is "active" breadcrumb_folder_items.append(breadcrumb_item) current_item = current_item.parent if current_item: # In last iteration, the parent is None, and there is no more breadcrumb item to build next_url = tg.url('/workspaces/{}/folders/{}'.format(workspace_id, current_item.content_id)) for item in reversed(breadcrumb_folder_items): breadcrumb.append(item) return breadcrumb
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 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 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_tree_item_for_menu_api_tree(item: NodeTreeItem, context: Context): if isinstance(item.node, Content): ContentType.fill_url(item.node) return DictLikeClass( id=CST.TREEVIEW_MENU.ID_TEMPLATE__FULL.format(item.node.workspace_id, item.node.content_id), children=True if ContentType.Folder==item.node.type and len(item.children)<=0 else context.toDict(item.children), text=item.node.get_label(), a_attr={'href': context.url(ContentType.fill_url(item.node)) }, li_attr={'title': item.node.get_label()}, # type='folder', type=item.node.type, state={'opened': True if ContentType.Folder==item.node.type and len(item.children)>0 else False, 'selected': item.is_selected} ) elif isinstance(item.node, Workspace): return DictLikeClass( id=CST.TREEVIEW_MENU.ID_TEMPLATE__WORKSPACE_ONLY.format(item.node.workspace_id), children=True if len(item.children)<=0 else context.toDict(item.children), text=item.node.label, a_attr={'href': context.url(ContentType.fill_url_for_workspace(item.node))}, li_attr={'title': item.node.get_label()}, type='workspace', state={'opened': True if len(item.children)>0 else False, 'selected': item.is_selected} )
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_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, 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 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 test_serialize_Content_comment_THREAD(self): wor = Workspace() wor.workspace_id = 4 fol = Content() fol.type = ContentType.Folder fol.content_id = 72 fol.workspace = wor par = Content() par.type = ContentType.Thread par.content_id = 37 par.parent = fol par.workspace = wor par.created = datetime.now() obj = Content() obj.type = ContentType.Comment obj.content_id = 132 obj.label = 'some label' obj.description = 'Some Description' obj.parent = par obj.created = datetime.now() print('LANGUAGES #2 ARE', tg.i18n.get_lang()) res = Context(CTX.THREAD).toDict(obj) eq_(res.__class__, DictLikeClass, res) ok_('label' in res.keys()) eq_(obj.label, res.label, res) ok_('content' in res.keys()) eq_(obj.description, res.content, res) ok_('created' in res.keys()) ok_('icon' in res.keys()) eq_(ContentType.get_icon(obj.type), res.icon, res) ok_('delete' in res.urls.keys()) eq_(10, len(res.keys()), len(res.keys()))
def serialize_content_for_folder_content_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 item = None if ContentType.Thread == content.type: item = Context(CTX.THREADS).toDict(content) item.type = context.toDict(content_type) item.folder = DictLikeClass({'id': content.parent_id}) if content.parent else None item.workspace = DictLikeClass({'id': content.workspace.workspace_id}) if content.workspace else None item.last_activity = DictLikeClass({'date': last_activity_date, 'label': last_activity_date_formatted, 'delta': last_activity_label}) comments = content.get_comments() if len(comments)>1: item.notes = _('{nb} messages').format(nb=len(comments)) else: item.notes = _('1 message') elif ContentType.File == content.type: item = Context(CTX.CONTENT_LIST).toDict(content) if len(content.revisions)>1: item.notes = _('{nb} revisions').format(nb=len(content.revisions)) else: item.notes = _('1 revision') elif ContentType.Folder == content.type: item = Context(CTX.CONTENT_LIST).toDict(content) item.notes = '' folder_nb = content.get_child_nb(ContentType.Folder) if folder_nb == 1: item.notes += _('1 subfolder<br/>\n') elif folder_nb > 1: item.notes += _('{} subfolders<br/>').format(folder_nb) file_nb = content.get_child_nb(ContentType.File, ContentStatus.OPEN) if file_nb == 1: item.notes += _('1 open file<br/>\n') elif file_nb > 1: item.notes += _('{} open files<br/>').format(file_nb) thread_nb = content.get_child_nb(ContentType.Thread, ContentStatus.OPEN) if thread_nb == 1: item.notes += _('1 open thread<br/>\n') elif thread_nb > 1: item.notes += _('{} open threads<br/>').format(thread_nb) page_nb = content.get_child_nb(ContentType.Page, ContentStatus.OPEN) if page_nb == 1: item.notes += _('1 open page<br/>\n') elif page_nb > 1: item.notes += _('{} open pages<br/>').format(page_nb) else: item = Context(CTX.CONTENT_LIST).toDict(content) item.notes = '' item.is_deleted = content.is_deleted item.is_archived = content.is_archived item.is_editable = content.is_editable return item
def serialize_breadcrumb_item(content_type: ContentType, context: Context): return DictLikeClass(content_type.toDict())