ソースを参照

Closes #232: Integrates preview generator feature

Adrien Panay 7 年 前
コミット
3b425d0a05

+ 1 - 1
tracim/development.ini.base ファイルの表示

@@ -35,7 +35,7 @@ full_stack = true
35 35
 # You can set french as default language by uncommenting next line
36 36
 # lang = fr
37 37
 cache_dir = %(here)s/data
38
-preview_cache_dir = '/tmp/tracim/cache/previews/'
38
+preview_cache_dir = /tmp/tracim/cache/previews/
39 39
 beaker.session.key = tracim
40 40
 beaker.session.secret = 3283411b-1904-4554-b0e1-883863b53080
41 41
 

File diff suppressed because it is too large
+ 308 - 222
tracim/tracim/controllers/content.py


+ 58 - 95
tracim/tracim/controllers/page.py ファイルの表示

@@ -1,6 +1,8 @@
1 1
 import tg
2
+from tg import expose
3
+from tg import tmpl_context
2 4
 from preview_generator.manager import PreviewManager
3
-from tg import expose, tmpl_context
5
+
4 6
 from tracim.config.app_cfg import CFG
5 7
 from tracim.controllers import TIMRestController
6 8
 from tracim.lib.content import ContentApi
@@ -8,6 +10,7 @@ from tracim.model.data import ContentType
8 10
 
9 11
 __all__ = ['PagesController']
10 12
 
13
+
11 14
 class PagesController(TIMRestController):
12 15
 
13 16
     @expose()
@@ -20,118 +23,78 @@ class PagesController(TIMRestController):
20 23
         return 'all the pages of document {}'.format(file_id)
21 24
 
22 25
     @expose(content_type='image/jpeg')
23
-    def get_one(self, page_id: int, revision_id: int=None, *args, **kwargs):
26
+    def get_one(self,
27
+                page_id: str='-1',
28
+                revision_id: str=None,
29
+                size: int=300,
30
+                *args, **kwargs):
24 31
         file_id = int(tg.request.controller_state.routing_args.get('file_id'))
25
-
26
-        # For now it's done through database content
27
-        # but soon it'll be with disk access
28
-
32
+        page = int(page_id)
33
+        revision_id = int(revision_id) if revision_id != 'latest' else None
34
+        cache_path = CFG.get_instance().PREVIEW_CACHE
35
+        preview_manager = PreviewManager(cache_path, create_folder=True)
29 36
         user = tmpl_context.current_user
30
-        content_api = ContentApi(
31
-            user,
32
-            show_archived=True,
33
-            show_deleted=True,
34
-        )
37
+        content_api = ContentApi(user,
38
+                                 show_archived=True,
39
+                                 show_deleted=True)
35 40
         if revision_id:
36 41
             file_path = content_api.get_one_revision_filepath(revision_id)
37 42
         else:
38 43
             file = content_api.get_one(file_id, self._item_type)
39 44
             file_path = content_api.get_one_revision_filepath(file.revision_id)
40
-
41
-        cfg = CFG.get_instance()
42
-        cache_path = cfg.PREVIEW_CACHE
43
-
44
-        preview_manager = PreviewManager(cache_path, create_folder=True)
45
-        path = preview_manager.get_jpeg_preview(
46
-            file_path=file_path,
47
-            page=page_id,
48
-            height=500,
49
-            width=500
50
-        )
51
-
45
+        path = preview_manager.get_jpeg_preview(file_path=file_path,
46
+                                                page=page,
47
+                                                height=size,
48
+                                                width=size)
52 49
         with open(path, 'rb') as large:
53 50
             return large.read()
54 51
 
55 52
     @expose(content_type='image/jpeg')
56
-    def high_quality(self, page_id: int, *args, **kwargs):
57
-        file_id = int(tg.request.controller_state.routing_args.get('file_id'))
58
-
59
-        # For now it's done through database content
60
-        # but soon it'll be with disk access
61
-
62
-        user = tmpl_context.current_user
63
-        content_api = ContentApi(
64
-            user,
65
-            show_archived=True,
66
-            show_deleted=True,
67
-        )
68
-        file_name = content_api.get_one(file_id, self._item_type).file_name
69
-        cache_path = '/home/alexis/Pictures/cache/'
70
-
71
-        preview_manager = PreviewManager(cache_path, create_folder=True)
72
-        path = preview_manager.get_jpeg_preview(
73
-            file_path='/home/alexis/Pictures/cache/{}'.format(file_name),
74
-            page=page_id,
75
-            height=5000,
76
-            width=5000
77
-        )
78
-
79
-        with open(path, 'rb') as large:
80
-            return large.read()
53
+    def high_quality(self,
54
+                     page_id: str='-1',
55
+                     revision_id: int=None,
56
+                     size: int=1000,
57
+                     *args, **kwargs):
58
+        result = self.get_one(page_id=page_id,
59
+                              revision_id=revision_id,
60
+                              size=size,
61
+                              args=args,
62
+                              kwargs=kwargs)
63
+        return result
81 64
 
82 65
     @expose(content_type='application/pdf')
83
-    def download_pdf_full(self, *args, **kwargs):
84
-        file_id = int(tg.request.controller_state.routing_args.get('file_id'))
85
-
86
-        # For now it's done through database content
87
-        # but soon it'll be with disk access
88
-
89
-        user = tmpl_context.current_user
90
-        content_api = ContentApi(
91
-            user,
92
-            show_archived=True,
93
-            show_deleted=True,
94
-        )
95
-        file_name = content_api.get_one(file_id, self._item_type).file_name
96
-        cache_path = '/home/alexis/Pictures/cache/'
97
-
98
-        preview_manager = PreviewManager(cache_path, create_folder=True)
99
-        path = preview_manager.get_pdf_preview(
100
-            file_path='/home/alexis/Pictures/cache/{}'.format(file_name),
101
-        )
102
-
103
-        tg.response.headers['Content-Disposition'] = \
104
-            str('attachment; filename="{}"'.format(file_name))
105
-        with open(path, 'rb') as pdf:
106
-            return pdf.read()
66
+    def download_pdf_full(self,
67
+                          page_id: str,
68
+                          revision_id: str='-1',
69
+                          *args, **kwargs):
70
+        return self.download_pdf_one(page_id='-1',
71
+                                     revision_id=revision_id,
72
+                                     args=args, kwargs=kwargs)
107 73
 
108 74
     @expose(content_type='application/pdf')
109
-    def download_pdf_one(self, page_id: int, *args, **kwargs):
75
+    def download_pdf_one(self,
76
+                         page_id: str,
77
+                         revision_id: str=None,
78
+                         *args, **kwargs):
110 79
         file_id = int(tg.request.controller_state.routing_args.get('file_id'))
111
-        page_id = int(page_id)
112
-        # page_id = int(tg.request.controller_state.routing_args.get('page_id'))
113
-
114
-        # For now it's done through database content
115
-        # but soon it'll be with disk access
116
-
117
-        user = tmpl_context.current_user
118
-        content_api = ContentApi(
119
-            user,
120
-            show_archived=True,
121
-            show_deleted=True,
122
-        )
123
-        file_name = content_api.get_one(file_id, self._item_type).file_name
124
-
125
-        cache_path = '/home/alexis/Pictures/cache/'
126
-
80
+        revision_id = int(revision_id) if revision_id != 'latest' else None
81
+        page = int(page_id)
82
+        cache_path = CFG.get_instance().PREVIEW_CACHE
127 83
         preview_manager = PreviewManager(cache_path, create_folder=True)
128
-        path = preview_manager.get_pdf_preview(
129
-            file_path='/home/alexis/Pictures/cache/{}'.format(file_name),
130
-            page=page_id,
131
-        )
132
-
84
+        user = tmpl_context.current_user
85
+        content_api = ContentApi(user,
86
+                                 show_archived=True,
87
+                                 show_deleted=True)
88
+        file = content_api.get_one(file_id, self._item_type)
89
+        if revision_id:
90
+            file_path = content_api.get_one_revision_filepath(revision_id)
91
+        else:
92
+            file = content_api.get_one(file_id, self._item_type)
93
+            file_path = content_api.get_one_revision_filepath(file.revision_id)
94
+        path = preview_manager.get_pdf_preview(file_path=file_path,
95
+                                               page=page)
133 96
         tg.response.headers['Content-Disposition'] = \
134
-            str('attachment; filename="{}"'.format(file_name))
97
+            'attachment; filename="{}"'.format(file.file_name)
135 98
         with open(path, 'rb') as pdf:
136 99
             return pdf.read()
137 100
 

+ 7 - 4
tracim/tracim/controllers/previews.py ファイルの表示

@@ -1,24 +1,27 @@
1
+from tg import expose
2
+from tg import tmpl_context
3
+
1 4
 from tracim.controllers import TIMRestController
2
-from tg import expose, tmpl_context
3 5
 from tracim.controllers.page import PagesController
4 6
 
5 7
 __all__ = ['PreviewsController']
6 8
 
9
+
7 10
 class PreviewsController(TIMRestController):
8 11
 
9 12
     pages = PagesController()
10 13
 
11 14
     @expose()
12
-    def _default(self, *args, **kwargs):
15
+    def _default(self, *args, **kwargs) -> str:
13 16
         return '<h2> Error Loading Page</h2>'
14 17
 
15 18
     @expose()
16
-    def get_all(self, *args, **kwargs):
19
+    def get_all(self, *args, **kwargs) -> str:
17 20
         print('getall _ document')
18 21
         return 'all the files'
19 22
 
20 23
     @expose()
21
-    def get_one(self, file_id, *args, **kwargs):
24
+    def get_one(self, file_id: int, *args, **kwargs) -> str:
22 25
         print('getone _ document')
23 26
         tmpl_context.file = file_id
24 27
         return 'File n°{}'.format(file_id)

+ 15 - 26
tracim/tracim/controllers/root.py ファイルの表示

@@ -1,5 +1,4 @@
1 1
 # -*- coding: utf-8 -*-
2
-import tg
3 2
 from tg import expose
4 3
 from tg import flash
5 4
 from tg import lurl
@@ -9,32 +8,29 @@ from tg import request
9 8
 from tg import require
10 9
 from tg import tmpl_context
11 10
 from tg import url
12
-
13 11
 from tg.i18n import ugettext as _
14
-from tracim.controllers.api import APIController
15
-from tracim.controllers.content import ContentController
16
-from tracim.controllers.previews import PreviewsController
17
-
18
-from tracim.lib import CST
19
-from tracim.lib.base import logger
20
-from tracim.lib.user import CurrentUserGetterApi
21
-from tracim.lib.content import ContentApi
22 12
 
23 13
 from tracim.controllers import StandardController
24 14
 from tracim.controllers.admin import AdminController
15
+from tracim.controllers.api import APIController
16
+from tracim.controllers.calendar import CalendarConfigController
17
+from tracim.controllers.calendar import CalendarController
18
+from tracim.controllers.content import ContentController
25 19
 from tracim.controllers.debug import DebugController
26 20
 from tracim.controllers.error import ErrorController
27 21
 from tracim.controllers.help import HelpController
28
-from tracim.controllers.calendar import CalendarController
29
-from tracim.controllers.calendar import CalendarConfigController
22
+from tracim.controllers.previews import PreviewsController
30 23
 from tracim.controllers.user import UserRestController
31 24
 from tracim.controllers.workspace import UserWorkspaceRestController
25
+from tracim.lib import CST
26
+from tracim.lib.base import logger
27
+from tracim.lib.content import ContentApi
28
+from tracim.lib.user import CurrentUserGetterApi
32 29
 from tracim.lib.utils import replace_reset_password_templates
33
-
34 30
 from tracim.model.data import ContentType
35
-from tracim.model.serializers import DictLikeClass
36
-from tracim.model.serializers import CTX
37 31
 from tracim.model.serializers import Context
32
+from tracim.model.serializers import CTX
33
+from tracim.model.serializers import DictLikeClass
38 34
 
39 35
 
40 36
 class RootController(StandardController):
@@ -59,7 +55,6 @@ class RootController(StandardController):
59 55
     debug = DebugController()
60 56
     error = ErrorController()
61 57
 
62
-
63 58
     # Rest controllers
64 59
     workspaces = UserWorkspaceRestController()
65 60
     user = UserRestController()
@@ -78,7 +73,6 @@ class RootController(StandardController):
78 73
         super(RootController, self)._before(args, kw)
79 74
         tmpl_context.project_name = "tracim"
80 75
 
81
-
82 76
     @expose('tracim.templates.index')
83 77
     def index(self, came_from='', *args, **kwargs):
84 78
         if request.identity:
@@ -109,7 +103,6 @@ class RootController(StandardController):
109 103
         logger.info(self, 'came_from: {}'.format(kwargs))
110 104
         return self.index(came_from, args, *kwargs)
111 105
 
112
-
113 106
     @expose()
114 107
     def post_login(self, came_from=lurl('/home')):
115 108
         """
@@ -119,7 +112,7 @@ class RootController(StandardController):
119 112
         if not request.identity:
120 113
             login_counter = request.environ.get('repoze.who.logins', 0) + 1
121 114
             redirect(url('/login'),
122
-                params=dict(came_from=came_from, __logins=login_counter))
115
+                     params=dict(came_from=came_from, __logins=login_counter))
123 116
 
124 117
         user = CurrentUserGetterApi.get_current_user()
125 118
 
@@ -129,11 +122,11 @@ class RootController(StandardController):
129 122
     @expose()
130 123
     def post_logout(self, came_from=lurl('/')):
131 124
         """
132
-        Redirect the user to the initially requested page on logout and say  goodbye as well.
125
+        Redirect the user to the initially requested page on logout and say
126
+        goodbye as well.
133 127
         """
134 128
         flash(_('Successfully logged out. We hope to see you soon!'))
135 129
         redirect(came_from)
136
-        
137 130
 
138 131
     @require(predicates.not_anonymous())
139 132
     @expose('tracim.templates.home')
@@ -144,7 +137,6 @@ class RootController(StandardController):
144 137
         fake_api = Context(CTX.CURRENT_USER).toDict({
145 138
             'current_user': current_user_content})
146 139
 
147
-
148 140
         last_active_contents = ContentApi(user).get_last_active(None, ContentType.Any, None)
149 141
         fake_api.last_actives = Context(CTX.CONTENT_LIST).toDict(last_active_contents, 'contents', 'nb')
150 142
 
@@ -175,10 +167,9 @@ class RootController(StandardController):
175 167
         #
176 168
         # return DictLikeClass(result = dictified_user, fake_api=fake_api)
177 169
 
178
-
179 170
     @require(predicates.not_anonymous())
180 171
     @expose('tracim.templates.search.display')
181
-    def search(self, keywords = ''):
172
+    def search(self, keywords=''):
182 173
         from tracim.lib.content import ContentApi
183 174
 
184 175
         user = tmpl_context.current_user
@@ -199,5 +190,3 @@ class RootController(StandardController):
199 190
         search_results.keywords = keyword_list
200 191
 
201 192
         return DictLikeClass(fake_api=fake_api, search=search_results)
202
-
203
-

+ 12 - 12
tracim/tracim/lib/content.py ファイルの表示

@@ -452,15 +452,15 @@ class ContentApi(object):
452 452
 
453 453
         return revision
454 454
 
455
-    # def get_one_revision_file(self, revision_id: int = None):
456
-    #     """
457
-    #     This function allows us to directly get a Python file object from its
458
-    #     revision identifier.
459
-    #     :param revision_id: The revision id of the file we want to return
460
-    #     :return: The corresponding Python file object
461
-    #     """
462
-    #     revision = self.get_one_revision(revision_id)
463
-    #     return DepotManager.get().get(revision.depot_file_uid)
455
+    # def get_one_revision_file(self, revision_id: int = None):
456
+    #     """
457
+    #     This function allows us to directly get a Python file object from its
458
+    #     revision identifier.
459
+    #     :param revision_id: The revision id of the file we want to return
460
+    #     :return: The corresponding Python file object
461
+    #     """
462
+    #     revision = self.get_one_revision(revision_id)
463
+    #     return DepotManager.get().get(revision.depot_file_uid)
464 464
 
465 465
     def get_one_revision_filepath(self, revision_id: int = None) -> str:
466 466
         """
@@ -472,9 +472,9 @@ class ContentApi(object):
472 472
         revision = self.get_one_revision(revision_id)
473 473
 
474 474
         dpt = DepotManager.get()
475
-        # python 3.6 PEP 526 -- Syntax for Variable Annotations
476
-        # https://www.python.org/dev/peps/pep-0526/
477
-        # dpt_file_path: str = dpt.get(dpt_stored_file)._file_path
475
+        # python 3.6 PEP 526 -- Syntax for Variable Annotations
476
+        # https://www.python.org/dev/peps/pep-0526/
477
+        # dpt_file_path: str = dpt.get(dpt_stored_file)._file_path
478 478
         dpt_stored_file = dpt.get(revision.depot_file_uid)
479 479
         dpt_file_path = dpt.get(dpt_stored_file)._file_path
480 480
 

+ 84 - 65
tracim/tracim/templates/file/getone.mak ファイルの表示

@@ -100,71 +100,6 @@
100 100
     % endif
101 101
 
102 102
     <div class="content__detail file">
103
-        <div style="width: 15%;height: 100%;border:5px solid #606060;">
104
-            <a id="preview_link"><img id='preview' alt="Preview" style="width:100%;height:100%"></a>
105
-            <table style="width:100%;height:20%;">
106
-                <tr>
107
-                    <td rowspan="2">
108
-                        <button type="button" id="prev" onclick="previous_page()" style="width:100%;height:100%;"> - </button>
109
-                    </td>
110
-                    <td>
111
-                        <a id="dl_one_pdf" style=""> Download the page </a>
112
-                    </td>
113
-                    <td rowspan="2">
114
-                        <button type="button" id="next" onclick="next_page()" style="width:100%;height:100%;"> + </button>
115
-                    </td>
116
-                </tr>
117
-                <tr>
118
-                    <td >
119
-                        <a id="dl_full_pdf" style=""> Download all </a>
120
-                    </td>
121
-                </tr>
122
-            </table>
123
-
124
-            <script type="text/javascript">
125
-                var nb_page = parseInt(${nb_page});
126
-                console.log(nb_page);
127
-                var page = 0;
128
-                var urls = [];
129
-                % for one_url in url:
130
-                urls.push('${one_url}');
131
-                % endfor
132
-                console.log(urls);
133
-                document.getElementById('preview').src = urls[page];
134
-                refresh_button();
135
-
136
-                function next_page(){
137
-                    page = page+1;
138
-                    console.log('page next');
139
-                    console.log(urls[page]);
140
-                    document.getElementById('preview').src = urls[page];
141
-                    refresh_button();
142
-                }
143
-
144
-                function previous_page(){
145
-                    page = page-1;
146
-                    console.log('page previous');
147
-                    console.log(urls[page]);
148
-                    document.getElementById('preview').src = urls[page];
149
-                    refresh_button();
150
-                }
151
-
152
-                function refresh_button(){
153
-                    console.log(page);
154
-                    document.getElementById('prev').disabled = false;
155
-                    document.getElementById('next').disabled = false;
156
-                    document.getElementById('dl_one_pdf').href = "/previews/${result.file.id}/pages/" + page + "/download_pdf_one";
157
-                    document.getElementById('dl_full_pdf').href = "/previews/${result.file.id}/pages/" + page + "/download_pdf_full";
158
-                    document.getElementById('preview_link').href = "/previews/${result.file.id}/pages/" + page + "/high_quality";
159
-                    if(page >= nb_page-1){
160
-                        document.getElementById('next').disabled = true;
161
-                    }
162
-                    if(page <= 0){
163
-                        document.getElementById('prev').disabled = true;
164
-                    }
165
-                }
166
-            </script>
167
-        </div>
168 103
         <% download_url = tg.url('/workspaces/{}/folders/{}/files/{}/download?revision_id={}'.format(result.file.workspace.id, result.file.parent.id,result.file.id,result.file.selected_revision)) %>
169 104
         <div class="t-half-spacer-above download-file-button">
170 105
             <a style="" class="btn btn-default" tittle="${_('Download the file')}"
@@ -176,6 +111,90 @@
176 111
         <div class="t-half-spacer-above">
177 112
             <table class="table table-hover table-condensed table-striped table-bordered">
178 113
                 <tr>
114
+                    <td class="tracim-title">${_('Preview')}</td>
115
+                    <td>
116
+                        <table>
117
+                            <tr>
118
+                                <td>
119
+                                    <button type="button" id="prev" onclick="previous_page()">
120
+                                        <span class="pull-left">
121
+                                            ${ICON.FA_FW('fa fa-chevron-left')}
122
+                                        </span>
123
+                                    </button>
124
+                                </td>
125
+                                <td>
126
+                                    <a id="preview_link"><img id='preview' alt="Preview"></a>
127
+                                </td>
128
+                                <td>
129
+                                    <button type="button" id="next" onclick="next_page()">
130
+                                        <span>
131
+                                            ${ICON.FA_FW('fa fa-chevron-right')}
132
+                                        </span>
133
+                                    </button>
134
+                                </td>
135
+                                <td>
136
+                                    <a type="button" id="dl_one_pdf">${_('this page')}
137
+                                        <span class="pull-left">
138
+                                            ${ICON.FA_FW('fa fa-download')}
139
+                                        </span>
140
+                                    </a>
141
+                                </td>
142
+                                <td>
143
+                                    <a type="button" id="dl_full_pdf">${_('all pages')}
144
+                                        <span class="pull-left">
145
+                                            ${ICON.FA_FW('fa fa-download')}
146
+                                        </span>
147
+                                    </a>
148
+                                </td>
149
+                            </tr>
150
+                        </table>
151
+
152
+                        <script type="text/javascript">
153
+                            var nb_page = parseInt(${nb_page});
154
+                            console.log(nb_page);
155
+                            var page = 0;
156
+                            var urls = [];
157
+                            % for one_url in url:
158
+                            urls.push('${one_url}');
159
+                            % endfor
160
+                            console.log(urls);
161
+                            document.getElementById('preview').src = urls[page];
162
+                            refresh_button();
163
+
164
+                            function next_page(){
165
+                                page = page+1;
166
+                                console.log('page next');
167
+                                console.log(urls[page]);
168
+                                document.getElementById('preview').src = urls[page];
169
+                                refresh_button();
170
+                            }
171
+
172
+                            function previous_page(){
173
+                                page = page-1;
174
+                                console.log('page previous');
175
+                                console.log(urls[page]);
176
+                                document.getElementById('preview').src = urls[page];
177
+                                refresh_button();
178
+                            }
179
+
180
+                            function refresh_button(){
181
+                                console.log(page);
182
+                                document.getElementById('prev').disabled = false;
183
+                                document.getElementById('next').disabled = false;
184
+                                document.getElementById('dl_one_pdf').href = "/previews/${result.file.id}/pages/" + page + "/download_pdf_one?revision_id=${result.file.selected_revision}";
185
+                                document.getElementById('dl_full_pdf').href = "/previews/${result.file.id}/pages/" + page + "/download_pdf_full?revision_id=${result.file.selected_revision}";
186
+                                document.getElementById('preview_link').href = "/previews/${result.file.id}/pages/" + page + "/high_quality?revision_id=${result.file.selected_revision}";
187
+                                if(page >= nb_page-1){
188
+                                    document.getElementById('next').disabled = true;
189
+                                }
190
+                                if(page <= 0){
191
+                                    document.getElementById('prev').disabled = true;
192
+                                }
193
+                            }
194
+                        </script>
195
+                    </td>
196
+                </tr>
197
+                <tr>
179 198
                     <td class="tracim-title">${_('File')}</td>
180 199
                     <td>
181 200
                         <a href="${download_url}" tittle="${_('Download the file (last revision)')}">