浏览代码

Closes #232: Integrates preview generator feature

Adrien Panay 7 年前
父节点
当前提交
3b425d0a05

+ 1 - 1
tracim/development.ini.base 查看文件

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

文件差异内容过多而无法显示
+ 308 - 222
tracim/tracim/controllers/content.py


+ 58 - 95
tracim/tracim/controllers/page.py 查看文件

1
 import tg
1
 import tg
2
+from tg import expose
3
+from tg import tmpl_context
2
 from preview_generator.manager import PreviewManager
4
 from preview_generator.manager import PreviewManager
3
-from tg import expose, tmpl_context
5
+
4
 from tracim.config.app_cfg import CFG
6
 from tracim.config.app_cfg import CFG
5
 from tracim.controllers import TIMRestController
7
 from tracim.controllers import TIMRestController
6
 from tracim.lib.content import ContentApi
8
 from tracim.lib.content import ContentApi
8
 
10
 
9
 __all__ = ['PagesController']
11
 __all__ = ['PagesController']
10
 
12
 
13
+
11
 class PagesController(TIMRestController):
14
 class PagesController(TIMRestController):
12
 
15
 
13
     @expose()
16
     @expose()
20
         return 'all the pages of document {}'.format(file_id)
23
         return 'all the pages of document {}'.format(file_id)
21
 
24
 
22
     @expose(content_type='image/jpeg')
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
         file_id = int(tg.request.controller_state.routing_args.get('file_id'))
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
         user = tmpl_context.current_user
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
         if revision_id:
40
         if revision_id:
36
             file_path = content_api.get_one_revision_filepath(revision_id)
41
             file_path = content_api.get_one_revision_filepath(revision_id)
37
         else:
42
         else:
38
             file = content_api.get_one(file_id, self._item_type)
43
             file = content_api.get_one(file_id, self._item_type)
39
             file_path = content_api.get_one_revision_filepath(file.revision_id)
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
         with open(path, 'rb') as large:
49
         with open(path, 'rb') as large:
53
             return large.read()
50
             return large.read()
54
 
51
 
55
     @expose(content_type='image/jpeg')
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
     @expose(content_type='application/pdf')
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
     @expose(content_type='application/pdf')
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
         file_id = int(tg.request.controller_state.routing_args.get('file_id'))
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
         preview_manager = PreviewManager(cache_path, create_folder=True)
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
         tg.response.headers['Content-Disposition'] = \
96
         tg.response.headers['Content-Disposition'] = \
134
-            str('attachment; filename="{}"'.format(file_name))
97
+            'attachment; filename="{}"'.format(file.file_name)
135
         with open(path, 'rb') as pdf:
98
         with open(path, 'rb') as pdf:
136
             return pdf.read()
99
             return pdf.read()
137
 
100
 

+ 7 - 4
tracim/tracim/controllers/previews.py 查看文件

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

+ 15 - 26
tracim/tracim/controllers/root.py 查看文件

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

+ 12 - 12
tracim/tracim/lib/content.py 查看文件

452
 
452
 
453
         return revision
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
     def get_one_revision_filepath(self, revision_id: int = None) -> str:
465
     def get_one_revision_filepath(self, revision_id: int = None) -> str:
466
         """
466
         """
472
         revision = self.get_one_revision(revision_id)
472
         revision = self.get_one_revision(revision_id)
473
 
473
 
474
         dpt = DepotManager.get()
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
         dpt_stored_file = dpt.get(revision.depot_file_uid)
478
         dpt_stored_file = dpt.get(revision.depot_file_uid)
479
         dpt_file_path = dpt.get(dpt_stored_file)._file_path
479
         dpt_file_path = dpt.get(dpt_stored_file)._file_path
480
 
480
 

+ 84 - 65
tracim/tracim/templates/file/getone.mak 查看文件

100
     % endif
100
     % endif
101
 
101
 
102
     <div class="content__detail file">
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
         <% 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)) %>
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
         <div class="t-half-spacer-above download-file-button">
104
         <div class="t-half-spacer-above download-file-button">
170
             <a style="" class="btn btn-default" tittle="${_('Download the file')}"
105
             <a style="" class="btn btn-default" tittle="${_('Download the file')}"
176
         <div class="t-half-spacer-above">
111
         <div class="t-half-spacer-above">
177
             <table class="table table-hover table-condensed table-striped table-bordered">
112
             <table class="table table-hover table-condensed table-striped table-bordered">
178
                 <tr>
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
                     <td class="tracim-title">${_('File')}</td>
198
                     <td class="tracim-title">${_('File')}</td>
180
                     <td>
199
                     <td>
181
                         <a href="${download_url}" tittle="${_('Download the file (last revision)')}">
200
                         <a href="${download_url}" tittle="${_('Download the file (last revision)')}">