Ejemplo n.º 1
0
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))
Ejemplo n.º 2
0
 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
Ejemplo n.º 3
0
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))
Ejemplo n.º 4
0
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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
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
Ejemplo n.º 7
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})
    )
Ejemplo n.º 8
0
    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'])
Ejemplo n.º 9
0
 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))
Ejemplo n.º 10
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})
    )
Ejemplo n.º 11
0
 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
Ejemplo n.º 12
0
 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
Ejemplo n.º 13
0
 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
Ejemplo n.º 14
0
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
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
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
Ejemplo n.º 17
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
Ejemplo n.º 18
0
 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
Ejemplo n.º 19
0
 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
Ejemplo n.º 20
0
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)
Ejemplo n.º 21
0
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)
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
    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
Ejemplo n.º 24
0
    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
Ejemplo n.º 25
0
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
Ejemplo n.º 26
0
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)
Ejemplo n.º 27
0
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
Ejemplo n.º 28
0
    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
Ejemplo n.º 29
0
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
Ejemplo n.º 30
0
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
Ejemplo n.º 31
0
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
Ejemplo n.º 32
0
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
Ejemplo n.º 33
0
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
Ejemplo n.º 34
0
    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)
Ejemplo n.º 35
0
 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,
     )
Ejemplo n.º 36
0
    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)
Ejemplo n.º 37
0
    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)
Ejemplo n.º 38
0
 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,
     )
Ejemplo n.º 39
0
    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
Ejemplo n.º 40
0
    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))
Ejemplo n.º 41
0
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
Ejemplo n.º 42
0
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)
Ejemplo n.º 43
0
    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
Ejemplo n.º 44
0
 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'),
     }
Ejemplo n.º 45
0
 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
Ejemplo n.º 46
0
 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'),
     }
Ejemplo n.º 47
0
 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
Ejemplo n.º 48
0
    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
Ejemplo n.º 49
0
    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
Ejemplo n.º 50
0
    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
Ejemplo n.º 51
0
    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
Ejemplo n.º 52
0
    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
Ejemplo n.º 53
0
    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))
Ejemplo n.º 54
0
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
Ejemplo n.º 55
0
    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)
Ejemplo n.º 56
0
    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))
Ejemplo n.º 57
0
    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)
Ejemplo n.º 58
0
    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))
Ejemplo n.º 59
0
 def undelete(self, content: Content):
     content.owner = self._user
     content.is_deleted = False
     content.revision_type = ActionDescription.UNDELETION
Ejemplo n.º 60
0
 def delete(self, content: Content):
     content.owner = self._user
     content.is_deleted = True
     content.revision_type = ActionDescription.DELETION