Browse Source

add endpoint for previews

Guénaël Muller 6 years ago
parent
commit
d27feca166

+ 34 - 0
tracim/models/context_models.py View File

53
         self.workspace_id = workspace_id
53
         self.workspace_id = workspace_id
54
 
54
 
55
 
55
 
56
+class ContentPreviewSizedPath(object):
57
+    """
58
+    Paths params with workspace id and content_id, width, heigth
59
+    """
60
+    def __init__(self, workspace_id: int, content_id: int, width: int, height: int) -> None:  # nopep8
61
+        self.content_id = content_id
62
+        self.workspace_id = workspace_id
63
+        self.width = width
64
+        self.height = height
65
+
66
+
67
+class RevisionPreviewSizedPath(object):
68
+    """
69
+    Paths params with workspace id and content_id, revision_id width, heigth
70
+    """
71
+    def __init__(self, workspace_id: int, content_id: int, revision_id: int, width: int, height: int) -> None:  # nopep8
72
+        self.content_id = content_id
73
+        self.revision_id = revision_id
74
+        self.workspace_id = workspace_id
75
+        self.width = width
76
+        self.height = height
77
+
78
+
56
 class CommentPath(object):
79
 class CommentPath(object):
57
     """
80
     """
58
     Paths params with workspace id and content_id and comment_id model
81
     Paths params with workspace id and content_id and comment_id model
68
         self.comment_id = comment_id
91
         self.comment_id = comment_id
69
 
92
 
70
 
93
 
94
+class PageQuery(object):
95
+    """
96
+    Page query model
97
+    """
98
+    def __init__(
99
+            self,
100
+            page: int = 0
101
+    ):
102
+        self.page = page
103
+
104
+
71
 class ContentFilter(object):
105
 class ContentFilter(object):
72
     """
106
     """
73
     Content filter model
107
     Content filter model

+ 141 - 6
tracim/views/contents_api/file_controller.py View File

20
 from tracim.lib.core.content import ContentApi
20
 from tracim.lib.core.content import ContentApi
21
 from tracim.views.controllers import Controller
21
 from tracim.views.controllers import Controller
22
 from tracim.views.core_api.schemas import FileContentSchema
22
 from tracim.views.core_api.schemas import FileContentSchema
23
+from tracim.views.core_api.schemas import ContentPreviewSizedPathSchema
24
+from tracim.views.core_api.schemas import RevisionPreviewSizedPathSchema
25
+from tracim.views.core_api.schemas import PageQuerySchema
23
 from tracim.views.core_api.schemas import WorkspaceAndContentRevisionIdPathSchema  # nopep8
26
 from tracim.views.core_api.schemas import WorkspaceAndContentRevisionIdPathSchema  # nopep8
24
 from tracim.views.core_api.schemas import FileRevisionSchema
27
 from tracim.views.core_api.schemas import FileRevisionSchema
25
 from tracim.views.core_api.schemas import SetContentStatusSchema
28
 from tracim.views.core_api.schemas import SetContentStatusSchema
126
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
129
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
127
     @require_workspace_role(UserRoleInWorkspace.READER)
130
     @require_workspace_role(UserRoleInWorkspace.READER)
128
     @require_content_types([file_type])
131
     @require_content_types([file_type])
132
+    @hapic.input_query(PageQuerySchema())
133
+    @hapic.input_path(WorkspaceAndContentIdPathSchema())
129
     @hapic.output_file([])
134
     @hapic.output_file([])
130
     def preview_pdf(self, context, request: TracimRequest, hapic_data=None):
135
     def preview_pdf(self, context, request: TracimRequest, hapic_data=None):
131
-        raise NotImplemented()
136
+        app_config = request.registry.settings['CFG']
137
+        preview_manager = PreviewManager(app_config.PREVIEW_CACHE_DIR, create_folder=True)  # nopep8
138
+        api = ContentApi(
139
+            current_user=request.current_user,
140
+            session=request.dbsession,
141
+            config=app_config,
142
+        )
143
+        content = api.get_one(
144
+            hapic_data.path.content_id,
145
+            content_type=ContentType.Any
146
+        )
147
+        file_path = api.get_one_revision_filepath(content.revision_id)
148
+        if hapic_data.query.page >= preview_manager.get_page_nb(file_path):
149
+            raise Exception('page {page} of content {content_id} does not exist'.format(
150
+                page=hapic_data.query.page,
151
+                content_id=content.content_id),
152
+            )
153
+        pdf_preview_path = preview_manager.get_pdf_preview(file_path, page=hapic_data.query.page)  # nopep8
154
+        return FileResponse(pdf_preview_path)
132
 
155
 
133
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
156
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
134
     @require_workspace_role(UserRoleInWorkspace.READER)
157
     @require_workspace_role(UserRoleInWorkspace.READER)
135
     @require_content_types([file_type])
158
     @require_content_types([file_type])
159
+    @hapic.input_path(WorkspaceAndContentIdPathSchema())
136
     @hapic.output_file([])
160
     @hapic.output_file([])
137
     def preview_pdf_full(self, context, request: TracimRequest, hapic_data=None):
161
     def preview_pdf_full(self, context, request: TracimRequest, hapic_data=None):
138
-        raise NotImplemented()
162
+        app_config = request.registry.settings['CFG']
163
+        preview_manager = PreviewManager(app_config.PREVIEW_CACHE_DIR, create_folder=True)  # nopep8
164
+        api = ContentApi(
165
+            current_user=request.current_user,
166
+            session=request.dbsession,
167
+            config=app_config,
168
+        )
169
+        content = api.get_one(
170
+            hapic_data.path.content_id,
171
+            content_type=ContentType.Any
172
+        )
173
+        file_path = api.get_one_revision_filepath(content.revision_id)
174
+        pdf_preview_path = preview_manager.get_pdf_preview(file_path)
175
+        return FileResponse(pdf_preview_path)
139
 
176
 
140
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
177
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
141
     @require_workspace_role(UserRoleInWorkspace.READER)
178
     @require_workspace_role(UserRoleInWorkspace.READER)
142
     @require_content_types([file_type])
179
     @require_content_types([file_type])
180
+    @hapic.input_path(WorkspaceAndContentRevisionIdPathSchema())
181
+    @hapic.input_query(PageQuerySchema())
143
     @hapic.output_file([])
182
     @hapic.output_file([])
144
     def preview_pdf_revision(self, context, request: TracimRequest, hapic_data=None):
183
     def preview_pdf_revision(self, context, request: TracimRequest, hapic_data=None):
145
-        raise NotImplemented()
184
+        app_config = request.registry.settings['CFG']
185
+        preview_manager = PreviewManager(app_config.PREVIEW_CACHE_DIR, create_folder=True)  # nopep8
186
+        api = ContentApi(
187
+            current_user=request.current_user,
188
+            session=request.dbsession,
189
+            config=app_config,
190
+        )
191
+        content = api.get_one(
192
+            hapic_data.path.content_id,
193
+            content_type=ContentType.Any
194
+        )
195
+        revision = api.get_one_revision(
196
+            revision_id=hapic_data.path.revision_id,
197
+            content=content
198
+        )
199
+        file_path = api.get_one_revision_filepath(revision.revision_id)
200
+        if hapic_data.query.page >= preview_manager.get_page_nb(file_path):
201
+            raise Exception('page {page} of content {content_id} does not exist'.format(
202
+                page=hapic_data.query.page,
203
+                content_id=content.content_id),
204
+            )
205
+        pdf_preview_path = preview_manager.get_pdf_preview(file_path, page=hapic_data.query.page)  # nopep8
206
+        return FileResponse(pdf_preview_path)
146
 
207
 
147
     # jpg
208
     # jpg
148
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
209
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
149
     @require_workspace_role(UserRoleInWorkspace.READER)
210
     @require_workspace_role(UserRoleInWorkspace.READER)
150
     @require_content_types([file_type])
211
     @require_content_types([file_type])
212
+    @hapic.input_path(WorkspaceAndContentIdPathSchema())
213
+    @hapic.input_query(PageQuerySchema())
151
     @hapic.output_file([])
214
     @hapic.output_file([])
152
     def preview_jpg(self, context, request: TracimRequest, hapic_data=None):
215
     def preview_jpg(self, context, request: TracimRequest, hapic_data=None):
153
-        raise NotImplemented()
216
+        app_config = request.registry.settings['CFG']
217
+        preview_manager = PreviewManager(app_config.PREVIEW_CACHE_DIR, create_folder=True)  # nopep8
218
+        api = ContentApi(
219
+            current_user=request.current_user,
220
+            session=request.dbsession,
221
+            config=app_config,
222
+        )
223
+        content = api.get_one(
224
+            hapic_data.path.content_id,
225
+            content_type=ContentType.Any
226
+        )
227
+        file_path = api.get_one_revision_filepath(content.revision_id)
228
+        if hapic_data.query.page >= preview_manager.get_page_nb(file_path):
229
+            raise Exception('page {page} of content {content_id} does not exist'.format(
230
+                page=hapic_data.query.page,
231
+                content_id=content.content_id),
232
+            )
233
+        jpg_preview_path = preview_manager.get_jpeg_preview(file_path, page=hapic_data.query.page)  # nopep8
234
+        return FileResponse(jpg_preview_path)
154
 
235
 
155
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
236
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
156
     @require_workspace_role(UserRoleInWorkspace.READER)
237
     @require_workspace_role(UserRoleInWorkspace.READER)
157
     @require_content_types([file_type])
238
     @require_content_types([file_type])
239
+    @hapic.input_query(PageQuerySchema())
240
+    @hapic.input_path(ContentPreviewSizedPathSchema())
158
     @hapic.output_file([])
241
     @hapic.output_file([])
159
     def sized_preview_jpg(self, context, request: TracimRequest, hapic_data=None):
242
     def sized_preview_jpg(self, context, request: TracimRequest, hapic_data=None):
160
-        raise NotImplemented()
243
+        app_config = request.registry.settings['CFG']
244
+        preview_manager = PreviewManager(app_config.PREVIEW_CACHE_DIR, create_folder=True)  # nopep8
245
+        api = ContentApi(
246
+            current_user=request.current_user,
247
+            session=request.dbsession,
248
+            config=app_config,
249
+        )
250
+        content = api.get_one(
251
+            hapic_data.path.content_id,
252
+            content_type=ContentType.Any
253
+        )
254
+        file_path = api.get_one_revision_filepath(content.revision_id)
255
+        if hapic_data.query.page >= preview_manager.get_page_nb(file_path):
256
+            raise Exception('page {page} of content {content_id} does not exist'.format(
257
+                page=hapic_data.query.page,
258
+                content_id=content.content_id),
259
+            )
260
+        jpg_preview_path = preview_manager.get_jpeg_preview(
261
+            file_path,
262
+            page=hapic_data.query.page,
263
+            width=hapic_data.path.width,
264
+            height=hapic_data.path.height,
265
+        )
266
+        return FileResponse(jpg_preview_path)
161
 
267
 
162
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
268
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
163
     @require_workspace_role(UserRoleInWorkspace.READER)
269
     @require_workspace_role(UserRoleInWorkspace.READER)
164
     @require_content_types([file_type])
270
     @require_content_types([file_type])
271
+    @hapic.input_path(RevisionPreviewSizedPathSchema())
272
+    @hapic.input_query(PageQuerySchema())
165
     @hapic.output_file([])
273
     @hapic.output_file([])
166
     def sized_preview_jpg_revision(self, context, request: TracimRequest, hapic_data=None):
274
     def sized_preview_jpg_revision(self, context, request: TracimRequest, hapic_data=None):
167
-        raise NotImplemented()
275
+        app_config = request.registry.settings['CFG']
276
+        preview_manager = PreviewManager(app_config.PREVIEW_CACHE_DIR, create_folder=True)  # nopep8
277
+        api = ContentApi(
278
+            current_user=request.current_user,
279
+            session=request.dbsession,
280
+            config=app_config,
281
+        )
282
+        content = api.get_one(
283
+            hapic_data.path.content_id,
284
+            content_type=ContentType.Any
285
+        )
286
+        revision = api.get_one_revision(
287
+            revision_id=hapic_data.path.revision_id,
288
+            content=content
289
+        )
290
+        file_path = api.get_one_revision_filepath(revision.revision_id)
291
+        if hapic_data.query.page >= preview_manager.get_page_nb(file_path):
292
+            raise Exception('page {page} of content {content_id} does not exist'.format(
293
+                page=hapic_data.query.page,
294
+                content_id=content.content_id),
295
+            )
296
+        jpg_preview_path = preview_manager.get_jpeg_preview(
297
+            file_path,
298
+            page=hapic_data.query.page,
299
+            width=hapic_data.path.width,
300
+            height=hapic_data.path.height,
301
+        )
302
+        return FileResponse(jpg_preview_path)
168
 
303
 
169
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
304
     @hapic.with_api_doc(tags=[FILE_ENDPOINTS_TAG])
170
     @require_workspace_role(UserRoleInWorkspace.READER)
305
     @require_workspace_role(UserRoleInWorkspace.READER)

+ 41 - 1
tracim/views/core_api/schemas.py View File

1
 # coding=utf-8
1
 # coding=utf-8
2
 import marshmallow
2
 import marshmallow
3
 from marshmallow import post_load
3
 from marshmallow import post_load
4
-from marshmallow.validate import OneOf
4
+from marshmallow.validate import OneOf, Range
5
 
5
 
6
 from tracim.lib.utils.utils import DATETIME_FORMAT
6
 from tracim.lib.utils.utils import DATETIME_FORMAT
7
 from tracim.models.auth import Profile
7
 from tracim.models.auth import Profile
10
 from tracim.models.contents import ContentTypeLegacy as ContentType
10
 from tracim.models.contents import ContentTypeLegacy as ContentType
11
 from tracim.models.contents import ContentStatusLegacy as ContentStatus
11
 from tracim.models.contents import ContentStatusLegacy as ContentStatus
12
 from tracim.models.context_models import ContentCreation
12
 from tracim.models.context_models import ContentCreation
13
+from tracim.models.context_models import ContentPreviewSizedPath
14
+from tracim.models.context_models import RevisionPreviewSizedPath
15
+from tracim.models.context_models import PageQuery
13
 from tracim.models.context_models import WorkspaceAndContentRevisionPath
16
 from tracim.models.context_models import WorkspaceAndContentRevisionPath
14
 from tracim.models.context_models import CommentCreation
17
 from tracim.models.context_models import CommentCreation
15
 from tracim.models.context_models import TextBasedContentUpdate
18
 from tracim.models.context_models import TextBasedContentUpdate
90
 class ContentIdPathSchema(marshmallow.Schema):
93
 class ContentIdPathSchema(marshmallow.Schema):
91
     content_id = marshmallow.fields.Int(example=6, required=True)
94
     content_id = marshmallow.fields.Int(example=6, required=True)
92
 
95
 
96
+
93
 class RevisionIdPathSchema(marshmallow.Schema):
97
 class RevisionIdPathSchema(marshmallow.Schema):
94
     revision_id = marshmallow.fields.Int(example=6, required=True)
98
     revision_id = marshmallow.fields.Int(example=6, required=True)
95
 
99
 
103
         return WorkspaceAndContentPath(**data)
107
         return WorkspaceAndContentPath(**data)
104
 
108
 
105
 
109
 
110
+class WidthAndHeightPathSchema(marshmallow.Schema):
111
+    width = marshmallow.fields.Int(example=256)
112
+    height = marshmallow.fields.Int(example=256)
113
+
114
+
106
 class WorkspaceAndContentRevisionIdPathSchema(
115
 class WorkspaceAndContentRevisionIdPathSchema(
107
     WorkspaceIdPathSchema,
116
     WorkspaceIdPathSchema,
108
     ContentIdPathSchema,
117
     ContentIdPathSchema,
113
         return WorkspaceAndContentRevisionPath(**data)
122
         return WorkspaceAndContentRevisionPath(**data)
114
 
123
 
115
 
124
 
125
+class ContentPreviewSizedPathSchema(
126
+    WorkspaceAndContentIdPathSchema,
127
+    WidthAndHeightPathSchema
128
+):
129
+    @post_load
130
+    def make_path_object(self, data):
131
+        return ContentPreviewSizedPath(**data)
132
+
133
+
134
+class RevisionPreviewSizedPathSchema(
135
+    WorkspaceAndContentRevisionIdPathSchema,
136
+    WidthAndHeightPathSchema
137
+):
138
+    @post_load
139
+    def make_path_object(self, data):
140
+        return RevisionPreviewSizedPath(**data)
141
+
142
+
116
 class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
143
 class CommentsPathSchema(WorkspaceAndContentIdPathSchema):
117
     comment_id = marshmallow.fields.Int(
144
     comment_id = marshmallow.fields.Int(
118
         example=6,
145
         example=6,
124
         return CommentPath(**data)
151
         return CommentPath(**data)
125
 
152
 
126
 
153
 
154
+class PageQuerySchema(marshmallow.Schema):
155
+    page = marshmallow.fields.Int(
156
+        example=2,
157
+        default=0,
158
+        description='allow to show a specific page of a pdf file',
159
+        validate=Range(min=0, error="Value must be positive or 0"),
160
+    )
161
+
162
+    @post_load
163
+    def make_page_query(self, data):
164
+        return PageQuery(**data)
165
+
166
+
127
 class FilterContentQuerySchema(marshmallow.Schema):
167
 class FilterContentQuerySchema(marshmallow.Schema):
128
     parent_id = marshmallow.fields.Int(
168
     parent_id = marshmallow.fields.Int(
129
         example=2,
169
         example=2,