Show More
@@ -68,6 +68,10 b' def includeme(config):' | |||
|
68 | 68 | pattern='/_markup_preview') |
|
69 | 69 | |
|
70 | 70 | config.add_route( |
|
71 | name='file_preview', | |
|
72 | pattern='/_file_preview') | |
|
73 | ||
|
74 | config.add_route( | |
|
71 | 75 | name='store_user_session_value', |
|
72 | 76 | pattern='/_store_session_attr') |
|
73 | 77 |
@@ -27,11 +27,12 b' from pyramid.view import view_config' | |||
|
27 | 27 | from rhodecode.apps._base import BaseAppView |
|
28 | 28 | from rhodecode.lib import helpers as h |
|
29 | 29 | from rhodecode.lib.auth import ( |
|
30 | LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, | |
|
31 | CSRFRequired) | |
|
30 | LoginRequired, NotAnonymous, HasRepoGroupPermissionAnyDecorator, CSRFRequired) | |
|
31 | from rhodecode.lib.codeblocks import filenode_as_lines_tokens | |
|
32 | 32 | from rhodecode.lib.index import searcher_from_config |
|
33 | 33 | from rhodecode.lib.utils2 import safe_unicode, str2bool, safe_int |
|
34 | 34 | from rhodecode.lib.ext_json import json |
|
35 | from rhodecode.lib.vcs.nodes import FileNode | |
|
35 | 36 | from rhodecode.model.db import ( |
|
36 | 37 | func, true, or_, case, in_filter_generator, Repository, RepoGroup, User, UserGroup) |
|
37 | 38 | from rhodecode.model.repo import RepoModel |
@@ -743,6 +744,34 b' class HomeView(BaseAppView):' | |||
|
743 | 744 | @LoginRequired() |
|
744 | 745 | @CSRFRequired() |
|
745 | 746 | @view_config( |
|
747 | route_name='file_preview', request_method='POST', | |
|
748 | renderer='string', xhr=True) | |
|
749 | def file_preview(self): | |
|
750 | # Technically a CSRF token is not needed as no state changes with this | |
|
751 | # call. However, as this is a POST is better to have it, so automated | |
|
752 | # tools don't flag it as potential CSRF. | |
|
753 | # Post is required because the payload could be bigger than the maximum | |
|
754 | # allowed by GET. | |
|
755 | ||
|
756 | text = self.request.POST.get('text') | |
|
757 | file_path = self.request.POST.get('file_path') | |
|
758 | ||
|
759 | renderer = h.renderer_from_filename(file_path) | |
|
760 | ||
|
761 | if renderer: | |
|
762 | return h.render(text, renderer=renderer, mentions=True) | |
|
763 | else: | |
|
764 | self.load_default_context() | |
|
765 | _render = self.request.get_partial_renderer( | |
|
766 | 'rhodecode:templates/files/file_content.mako') | |
|
767 | ||
|
768 | lines = filenode_as_lines_tokens(FileNode(file_path, text)) | |
|
769 | ||
|
770 | return _render('render_lines', lines) | |
|
771 | ||
|
772 | @LoginRequired() | |
|
773 | @CSRFRequired() | |
|
774 | @view_config( | |
|
746 | 775 | route_name='store_user_session_value', request_method='POST', |
|
747 | 776 | renderer='string', xhr=True) |
|
748 | 777 | def store_user_session_attr(self): |
@@ -25,6 +25,7 b' import shutil' | |||
|
25 | 25 | import tempfile |
|
26 | 26 | import collections |
|
27 | 27 | import urllib |
|
28 | import pathlib2 | |
|
28 | 29 | |
|
29 | 30 | from pyramid.httpexceptions import HTTPNotFound, HTTPBadRequest, HTTPFound |
|
30 | 31 | from pyramid.view import view_config |
@@ -42,7 +43,7 b' from rhodecode.lib.exceptions import Non' | |||
|
42 | 43 | from rhodecode.lib.codeblocks import ( |
|
43 | 44 | filenode_as_lines_tokens, filenode_as_annotated_lines_tokens) |
|
44 | 45 | from rhodecode.lib.utils2 import ( |
|
45 | convert_line_endings, detect_mode, safe_str, str2bool, safe_int, sha1) | |
|
46 | convert_line_endings, detect_mode, safe_str, str2bool, safe_int, sha1, safe_unicode) | |
|
46 | 47 | from rhodecode.lib.auth import ( |
|
47 | 48 | LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired) |
|
48 | 49 | from rhodecode.lib.vcs import path as vcspath |
@@ -87,7 +88,7 b' class RepoFilesView(RepoAppView):' | |||
|
87 | 88 | c.enable_downloads = self.db_repo.enable_downloads |
|
88 | 89 | return c |
|
89 | 90 | |
|
90 | def _ensure_not_locked(self): | |
|
91 | def _ensure_not_locked(self, commit_id='tip'): | |
|
91 | 92 | _ = self.request.translate |
|
92 | 93 | |
|
93 | 94 | repo = self.db_repo |
@@ -98,21 +99,40 b' class RepoFilesView(RepoAppView):' | |||
|
98 | 99 | 'warning') |
|
99 | 100 | files_url = h.route_path( |
|
100 | 101 | 'repo_files:default_path', |
|
101 |
repo_name=self.db_repo_name, commit_id= |
|
|
102 | repo_name=self.db_repo_name, commit_id=commit_id) | |
|
102 | 103 | raise HTTPFound(files_url) |
|
103 | 104 | |
|
104 | def check_branch_permission(self, branch_name): | |
|
105 | def forbid_non_head(self, is_head, f_path, commit_id='tip', json_mode=False): | |
|
106 | _ = self.request.translate | |
|
107 | ||
|
108 | if not is_head: | |
|
109 | message = _('You can only modify files with commit being a valid branch head.') | |
|
110 | h.flash(message, category='warning') | |
|
111 | ||
|
112 | if json_mode: | |
|
113 | return message | |
|
114 | ||
|
115 | files_url = h.route_path( | |
|
116 | 'repo_files', repo_name=self.db_repo_name, commit_id=commit_id, | |
|
117 | f_path=f_path) | |
|
118 | raise HTTPFound(files_url) | |
|
119 | ||
|
120 | def check_branch_permission(self, branch_name, commit_id='tip', json_mode=False): | |
|
105 | 121 | _ = self.request.translate |
|
106 | 122 | |
|
107 | 123 | rule, branch_perm = self._rhodecode_user.get_rule_and_branch_permission( |
|
108 | 124 | self.db_repo_name, branch_name) |
|
109 | 125 | if branch_perm and branch_perm not in ['branch.push', 'branch.push_force']: |
|
110 | h.flash( | |
|
111 | _('Branch `{}` changes forbidden by rule {}.').format(branch_name, rule), | |
|
112 |
|
|
|
126 | message = _('Branch `{}` changes forbidden by rule {}.').format( | |
|
127 | branch_name, rule) | |
|
128 | h.flash(message, 'warning') | |
|
129 | ||
|
130 | if json_mode: | |
|
131 | return message | |
|
132 | ||
|
113 | 133 | files_url = h.route_path( |
|
114 | 'repo_files:default_path', | |
|
115 | repo_name=self.db_repo_name, commit_id='tip') | |
|
134 | 'repo_files:default_path', repo_name=self.db_repo_name, commit_id=commit_id) | |
|
135 | ||
|
116 | 136 | raise HTTPFound(files_url) |
|
117 | 137 | |
|
118 | 138 | def _get_commit_and_path(self): |
@@ -146,8 +166,7 b' class RepoFilesView(RepoAppView):' | |||
|
146 | 166 | |
|
147 | 167 | _url = h.route_path( |
|
148 | 168 | 'repo_files_add_file', |
|
149 |
repo_name=self.db_repo_name, commit_id=0, f_path='' |
|
|
150 | _anchor='edit') | |
|
169 | repo_name=self.db_repo_name, commit_id=0, f_path='') | |
|
151 | 170 | |
|
152 | 171 | if h.HasRepoPermissionAny( |
|
153 | 172 | 'repository.write', 'repository.admin')(self.db_repo_name): |
@@ -217,7 +236,7 b' class RepoFilesView(RepoAppView):' | |||
|
217 | 236 | break |
|
218 | 237 | |
|
219 | 238 | # checked branches, means we only need to try to get the branch/commit_sha |
|
220 | if not repo.is_empty: | |
|
239 | if not repo.is_empty(): | |
|
221 | 240 | commit = repo.get_commit(commit_id=commit_id) |
|
222 | 241 | if commit: |
|
223 | 242 | branch_name = commit.branch |
@@ -276,6 +295,15 b' class RepoFilesView(RepoAppView):' | |||
|
276 | 295 | |
|
277 | 296 | return commit_id, ext, fileformat, content_type |
|
278 | 297 | |
|
298 | def create_pure_path(self, *parts): | |
|
299 | # Split paths and sanitize them, removing any ../ etc | |
|
300 | sanitized_path = [ | |
|
301 | x for x in pathlib2.PurePath(*parts).parts | |
|
302 | if x not in ['.', '..']] | |
|
303 | ||
|
304 | pure_path = pathlib2.PurePath(*sanitized_path) | |
|
305 | return pure_path | |
|
306 | ||
|
279 | 307 | @LoginRequired() |
|
280 | 308 | @HasRepoPermissionAnyDecorator( |
|
281 | 309 | 'repository.read', 'repository.write', 'repository.admin') |
@@ -1054,15 +1082,9 b' class RepoFilesView(RepoAppView):' | |||
|
1054 | 1082 | _branch_name, _sha_commit_id, is_head = \ |
|
1055 | 1083 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) |
|
1056 | 1084 | |
|
1057 | if not is_head: | |
|
1058 | h.flash(_('You can only delete files with commit ' | |
|
1059 | 'being a valid branch head.'), category='warning') | |
|
1060 | raise HTTPFound( | |
|
1061 | h.route_path('repo_files', | |
|
1062 | repo_name=self.db_repo_name, commit_id='tip', | |
|
1063 | f_path=f_path)) | |
|
1085 | self.forbid_non_head(is_head, f_path) | |
|
1086 | self.check_branch_permission(_branch_name) | |
|
1064 | 1087 | |
|
1065 | self.check_branch_permission(_branch_name) | |
|
1066 | 1088 | c.commit = self._get_commit_or_redirect(commit_id) |
|
1067 | 1089 | c.file = self._get_filenode_or_redirect(c.commit, f_path) |
|
1068 | 1090 | |
@@ -1088,13 +1110,7 b' class RepoFilesView(RepoAppView):' | |||
|
1088 | 1110 | _branch_name, _sha_commit_id, is_head = \ |
|
1089 | 1111 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) |
|
1090 | 1112 | |
|
1091 | if not is_head: | |
|
1092 | h.flash(_('You can only delete files with commit ' | |
|
1093 | 'being a valid branch head.'), category='warning') | |
|
1094 | raise HTTPFound( | |
|
1095 | h.route_path('repo_files', | |
|
1096 | repo_name=self.db_repo_name, commit_id='tip', | |
|
1097 | f_path=f_path)) | |
|
1113 | self.forbid_non_head(is_head, f_path) | |
|
1098 | 1114 | self.check_branch_permission(_branch_name) |
|
1099 | 1115 | |
|
1100 | 1116 | c.commit = self._get_commit_or_redirect(commit_id) |
@@ -1144,14 +1160,8 b' class RepoFilesView(RepoAppView):' | |||
|
1144 | 1160 | _branch_name, _sha_commit_id, is_head = \ |
|
1145 | 1161 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) |
|
1146 | 1162 | |
|
1147 | if not is_head: | |
|
1148 | h.flash(_('You can only edit files with commit ' | |
|
1149 | 'being a valid branch head.'), category='warning') | |
|
1150 | raise HTTPFound( | |
|
1151 | h.route_path('repo_files', | |
|
1152 | repo_name=self.db_repo_name, commit_id='tip', | |
|
1153 | f_path=f_path)) | |
|
1154 | self.check_branch_permission(_branch_name) | |
|
1163 | self.forbid_non_head(is_head, f_path, commit_id=commit_id) | |
|
1164 | self.check_branch_permission(_branch_name, commit_id=commit_id) | |
|
1155 | 1165 | |
|
1156 | 1166 | c.commit = self._get_commit_or_redirect(commit_id) |
|
1157 | 1167 | c.file = self._get_filenode_or_redirect(c.commit, f_path) |
@@ -1163,8 +1173,7 b' class RepoFilesView(RepoAppView):' | |||
|
1163 | 1173 | commit_id=c.commit.raw_id, f_path=f_path) |
|
1164 | 1174 | raise HTTPFound(files_url) |
|
1165 | 1175 | |
|
1166 | c.default_message = _( | |
|
1167 | 'Edited file {} via RhodeCode Enterprise').format(f_path) | |
|
1176 | c.default_message = _('Edited file {} via RhodeCode Enterprise').format(f_path) | |
|
1168 | 1177 | c.f_path = f_path |
|
1169 | 1178 | |
|
1170 | 1179 | return self._get_template_context(c) |
@@ -1181,32 +1190,23 b' class RepoFilesView(RepoAppView):' | |||
|
1181 | 1190 | commit_id, f_path = self._get_commit_and_path() |
|
1182 | 1191 | |
|
1183 | 1192 | self._ensure_not_locked() |
|
1184 | _branch_name, _sha_commit_id, is_head = \ | |
|
1185 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) | |
|
1186 | ||
|
1187 | if not is_head: | |
|
1188 | h.flash(_('You can only edit files with commit ' | |
|
1189 | 'being a valid branch head.'), category='warning') | |
|
1190 | raise HTTPFound( | |
|
1191 | h.route_path('repo_files', | |
|
1192 | repo_name=self.db_repo_name, commit_id='tip', | |
|
1193 | f_path=f_path)) | |
|
1194 | ||
|
1195 | self.check_branch_permission(_branch_name) | |
|
1196 | 1193 | |
|
1197 | 1194 | c.commit = self._get_commit_or_redirect(commit_id) |
|
1198 | 1195 | c.file = self._get_filenode_or_redirect(c.commit, f_path) |
|
1199 | 1196 | |
|
1200 | 1197 | if c.file.is_binary: |
|
1201 | raise HTTPFound( | |
|
1202 | h.route_path('repo_files', | |
|
1203 | repo_name=self.db_repo_name, | |
|
1204 | commit_id=c.commit.raw_id, | |
|
1205 | f_path=f_path)) | |
|
1198 | raise HTTPFound(h.route_path('repo_files', repo_name=self.db_repo_name, | |
|
1199 | commit_id=c.commit.raw_id, f_path=f_path)) | |
|
1200 | ||
|
1201 | _branch_name, _sha_commit_id, is_head = \ | |
|
1202 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) | |
|
1206 | 1203 | |
|
1207 | c.default_message = _( | |
|
1208 | 'Edited file {} via RhodeCode Enterprise').format(f_path) | |
|
1204 | self.forbid_non_head(is_head, f_path, commit_id=commit_id) | |
|
1205 | self.check_branch_permission(_branch_name, commit_id=commit_id) | |
|
1206 | ||
|
1207 | c.default_message = _('Edited file {} via RhodeCode Enterprise').format(f_path) | |
|
1209 | 1208 | c.f_path = f_path |
|
1209 | ||
|
1210 | 1210 | old_content = c.file.content |
|
1211 | 1211 | sl = old_content.splitlines(1) |
|
1212 | 1212 | first_line = sl[0] if sl else '' |
@@ -1217,20 +1217,25 b' class RepoFilesView(RepoAppView):' | |||
|
1217 | 1217 | content = convert_line_endings(r_post.get('content', ''), line_ending_mode) |
|
1218 | 1218 | |
|
1219 | 1219 | message = r_post.get('message') or c.default_message |
|
1220 |
org_ |
|
|
1220 | org_node_path = c.file.unicode_path | |
|
1221 | 1221 | filename = r_post['filename'] |
|
1222 | org_filename = c.file.name | |
|
1222 | ||
|
1223 | root_path = c.file.dir_path | |
|
1224 | pure_path = self.create_pure_path(root_path, filename) | |
|
1225 | node_path = safe_unicode(bytes(pure_path)) | |
|
1223 | 1226 | |
|
1224 | if content == old_content and filename == org_filename: | |
|
1225 | h.flash(_('No changes'), category='warning') | |
|
1226 | raise HTTPFound( | |
|
1227 | h.route_path('repo_commit', repo_name=self.db_repo_name, | |
|
1228 |
|
|
|
1227 | default_redirect_url = h.route_path('repo_commit', repo_name=self.db_repo_name, | |
|
1228 | commit_id=commit_id) | |
|
1229 | if content == old_content and node_path == org_node_path: | |
|
1230 | h.flash(_('No changes detected on {}').format(org_node_path), | |
|
1231 | category='warning') | |
|
1232 | raise HTTPFound(default_redirect_url) | |
|
1233 | ||
|
1229 | 1234 | try: |
|
1230 | 1235 | mapping = { |
|
1231 |
org_ |
|
|
1232 |
'org_filename': org_ |
|
|
1233 |
'filename': |
|
|
1236 | org_node_path: { | |
|
1237 | 'org_filename': org_node_path, | |
|
1238 | 'filename': node_path, | |
|
1234 | 1239 | 'content': content, |
|
1235 | 1240 | 'lexer': '', |
|
1236 | 1241 | 'op': 'mod', |
@@ -1238,7 +1243,7 b' class RepoFilesView(RepoAppView):' | |||
|
1238 | 1243 | } |
|
1239 | 1244 | } |
|
1240 | 1245 | |
|
1241 | ScmModel().update_nodes( | |
|
1246 | commit = ScmModel().update_nodes( | |
|
1242 | 1247 | user=self._rhodecode_db_user.user_id, |
|
1243 | 1248 | repo=self.db_repo, |
|
1244 | 1249 | message=message, |
@@ -1246,15 +1251,16 b' class RepoFilesView(RepoAppView):' | |||
|
1246 | 1251 | parent_commit=c.commit, |
|
1247 | 1252 | ) |
|
1248 | 1253 | |
|
1249 | h.flash( | |
|
1250 | _('Successfully committed changes to file `{}`').format( | |
|
1254 | h.flash(_('Successfully committed changes to file `{}`').format( | |
|
1251 | 1255 | h.escape(f_path)), category='success') |
|
1256 | default_redirect_url = h.route_path( | |
|
1257 | 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id) | |
|
1258 | ||
|
1252 | 1259 | except Exception: |
|
1253 | 1260 | log.exception('Error occurred during commit') |
|
1254 | 1261 | h.flash(_('Error occurred during commit'), category='error') |
|
1255 | raise HTTPFound( | |
|
1256 | h.route_path('repo_commit', repo_name=self.db_repo_name, | |
|
1257 | commit_id='tip')) | |
|
1262 | ||
|
1263 | raise HTTPFound(default_redirect_url) | |
|
1258 | 1264 | |
|
1259 | 1265 | @LoginRequired() |
|
1260 | 1266 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') |
@@ -1274,10 +1280,8 b' class RepoFilesView(RepoAppView):' | |||
|
1274 | 1280 | c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False) |
|
1275 | 1281 | if c.commit is None: |
|
1276 | 1282 | c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias) |
|
1277 | c.default_message = (_('Added file via RhodeCode Enterprise')) | |
|
1278 | c.f_path = f_path.lstrip('/') # ensure not relative path | |
|
1279 | 1283 | |
|
1280 | if self.rhodecode_vcs_repo.is_empty: | |
|
1284 | if self.rhodecode_vcs_repo.is_empty(): | |
|
1281 | 1285 | # for empty repository we cannot check for current branch, we rely on |
|
1282 | 1286 | # c.commit.branch instead |
|
1283 | 1287 | _branch_name = c.commit.branch |
@@ -1286,15 +1290,11 b' class RepoFilesView(RepoAppView):' | |||
|
1286 | 1290 | _branch_name, _sha_commit_id, is_head = \ |
|
1287 | 1291 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) |
|
1288 | 1292 | |
|
1289 | if not is_head: | |
|
1290 | h.flash(_('You can only add files with commit ' | |
|
1291 | 'being a valid branch head.'), category='warning') | |
|
1292 | raise HTTPFound( | |
|
1293 | h.route_path('repo_files', | |
|
1294 | repo_name=self.db_repo_name, commit_id='tip', | |
|
1295 | f_path=f_path)) | |
|
1293 | self.forbid_non_head(is_head, f_path, commit_id=commit_id) | |
|
1294 | self.check_branch_permission(_branch_name, commit_id=commit_id) | |
|
1296 | 1295 | |
|
1297 | self.check_branch_permission(_branch_name) | |
|
1296 | c.default_message = (_('Added file via RhodeCode Enterprise')) | |
|
1297 | c.f_path = f_path.lstrip('/') # ensure not relative path | |
|
1298 | 1298 | |
|
1299 | 1299 | return self._get_template_context(c) |
|
1300 | 1300 | |
@@ -1311,14 +1311,19 b' class RepoFilesView(RepoAppView):' | |||
|
1311 | 1311 | |
|
1312 | 1312 | self._ensure_not_locked() |
|
1313 | 1313 | |
|
1314 | r_post = self.request.POST | |
|
1315 | ||
|
1316 | c.commit = self._get_commit_or_redirect( | |
|
1317 | commit_id, redirect_after=False) | |
|
1314 | c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False) | |
|
1318 | 1315 | if c.commit is None: |
|
1319 | 1316 | c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias) |
|
1320 | 1317 | |
|
1321 | if self.rhodecode_vcs_repo.is_empty: | |
|
1318 | # calculate redirect URL | |
|
1319 | if self.rhodecode_vcs_repo.is_empty(): | |
|
1320 | default_redirect_url = h.route_path( | |
|
1321 | 'repo_summary', repo_name=self.db_repo_name) | |
|
1322 | else: | |
|
1323 | default_redirect_url = h.route_path( | |
|
1324 | 'repo_commit', repo_name=self.db_repo_name, commit_id='tip') | |
|
1325 | ||
|
1326 | if self.rhodecode_vcs_repo.is_empty(): | |
|
1322 | 1327 | # for empty repository we cannot check for current branch, we rely on |
|
1323 | 1328 | # c.commit.branch instead |
|
1324 | 1329 | _branch_name = c.commit.branch |
@@ -1327,70 +1332,42 b' class RepoFilesView(RepoAppView):' | |||
|
1327 | 1332 | _branch_name, _sha_commit_id, is_head = \ |
|
1328 | 1333 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) |
|
1329 | 1334 | |
|
1330 | if not is_head: | |
|
1331 | h.flash(_('You can only add files with commit ' | |
|
1332 | 'being a valid branch head.'), category='warning') | |
|
1333 | raise HTTPFound( | |
|
1334 | h.route_path('repo_files', | |
|
1335 | repo_name=self.db_repo_name, commit_id='tip', | |
|
1336 | f_path=f_path)) | |
|
1337 | ||
|
1338 | self.check_branch_permission(_branch_name) | |
|
1335 | self.forbid_non_head(is_head, f_path, commit_id=commit_id) | |
|
1336 | self.check_branch_permission(_branch_name, commit_id=commit_id) | |
|
1339 | 1337 | |
|
1340 | 1338 | c.default_message = (_('Added file via RhodeCode Enterprise')) |
|
1341 | 1339 | c.f_path = f_path |
|
1340 | ||
|
1341 | r_post = self.request.POST | |
|
1342 | message = r_post.get('message') or c.default_message | |
|
1343 | filename = r_post.get('filename') | |
|
1342 | 1344 | unix_mode = 0 |
|
1343 | 1345 | content = convert_line_endings(r_post.get('content', ''), unix_mode) |
|
1344 | 1346 | |
|
1345 | message = r_post.get('message') or c.default_message | |
|
1346 | filename = r_post.get('filename') | |
|
1347 | location = r_post.get('location', '') # dir location | |
|
1348 | file_obj = r_post.get('upload_file', None) | |
|
1349 | ||
|
1350 | if file_obj is not None and hasattr(file_obj, 'filename'): | |
|
1351 | filename = r_post.get('filename_upload') | |
|
1352 | content = file_obj.file | |
|
1353 | ||
|
1354 | if hasattr(content, 'file'): | |
|
1355 | # non posix systems store real file under file attr | |
|
1356 | content = content.file | |
|
1357 | ||
|
1358 | if self.rhodecode_vcs_repo.is_empty: | |
|
1359 | default_redirect_url = h.route_path( | |
|
1360 | 'repo_summary', repo_name=self.db_repo_name) | |
|
1361 | else: | |
|
1362 | default_redirect_url = h.route_path( | |
|
1363 | 'repo_commit', repo_name=self.db_repo_name, commit_id='tip') | |
|
1364 | ||
|
1347 | if not filename: | |
|
1365 | 1348 | # If there's no commit, redirect to repo summary |
|
1366 | 1349 | if type(c.commit) is EmptyCommit: |
|
1367 | 1350 | redirect_url = h.route_path( |
|
1368 | 1351 | 'repo_summary', repo_name=self.db_repo_name) |
|
1369 | 1352 | else: |
|
1370 | 1353 | redirect_url = default_redirect_url |
|
1371 | ||
|
1372 | if not filename: | |
|
1373 | h.flash(_('No filename'), category='warning') | |
|
1354 | h.flash(_('No filename specified'), category='warning') | |
|
1374 | 1355 | raise HTTPFound(redirect_url) |
|
1375 | 1356 | |
|
1376 | # extract the location from filename, | |
|
1377 | # allows using foo/bar.txt syntax to create subdirectories | |
|
1378 | subdir_loc = filename.rsplit('/', 1) | |
|
1379 | if len(subdir_loc) == 2: | |
|
1380 | location = os.path.join(location, subdir_loc[0]) | |
|
1357 | root_path = f_path | |
|
1358 | pure_path = self.create_pure_path(root_path, filename) | |
|
1359 | node_path = safe_unicode(bytes(pure_path).lstrip('/')) | |
|
1381 | 1360 | |
|
1382 | # strip all crap out of file, just leave the basename | |
|
1383 | filename = os.path.basename(filename) | |
|
1384 | node_path = os.path.join(location, filename) | |
|
1385 | 1361 | author = self._rhodecode_db_user.full_contact |
|
1386 | ||
|
1387 | try: | |
|
1388 | 1362 |
|
|
1389 | 1363 |
|
|
1390 | 1364 |
|
|
1391 | 1365 |
|
|
1392 | 1366 |
|
|
1393 | ScmModel().create_nodes( | |
|
1367 | ||
|
1368 | try: | |
|
1369 | ||
|
1370 | commit = ScmModel().create_nodes( | |
|
1394 | 1371 | user=self._rhodecode_db_user.user_id, |
|
1395 | 1372 | repo=self.db_repo, |
|
1396 | 1373 | message=message, |
@@ -1399,13 +1376,15 b' class RepoFilesView(RepoAppView):' | |||
|
1399 | 1376 | author=author, |
|
1400 | 1377 | ) |
|
1401 | 1378 | |
|
1402 | h.flash( | |
|
1403 | _('Successfully committed new file `{}`').format( | |
|
1379 | h.flash(_('Successfully committed new file `{}`').format( | |
|
1404 | 1380 | h.escape(node_path)), category='success') |
|
1381 | ||
|
1382 | default_redirect_url = h.route_path( | |
|
1383 | 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id) | |
|
1384 | ||
|
1405 | 1385 | except NonRelativePathError: |
|
1406 | 1386 | log.exception('Non Relative path found') |
|
1407 | h.flash(_( | |
|
1408 | 'The location specified must be a relative path and must not ' | |
|
1387 | h.flash(_('The location specified must be a relative path and must not ' | |
|
1409 | 1388 | 'contain .. in the path'), category='warning') |
|
1410 | 1389 | raise HTTPFound(default_redirect_url) |
|
1411 | 1390 | except (NodeError, NodeAlreadyExistsError) as e: |
@@ -1415,3 +1394,135 b' class RepoFilesView(RepoAppView):' | |||
|
1415 | 1394 | h.flash(_('Error occurred during commit'), category='error') |
|
1416 | 1395 | |
|
1417 | 1396 | raise HTTPFound(default_redirect_url) |
|
1397 | ||
|
1398 | @LoginRequired() | |
|
1399 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') | |
|
1400 | @CSRFRequired() | |
|
1401 | @view_config( | |
|
1402 | route_name='repo_files_upload_file', request_method='POST', | |
|
1403 | renderer='json_ext') | |
|
1404 | def repo_files_upload_file(self): | |
|
1405 | _ = self.request.translate | |
|
1406 | c = self.load_default_context() | |
|
1407 | commit_id, f_path = self._get_commit_and_path() | |
|
1408 | ||
|
1409 | self._ensure_not_locked() | |
|
1410 | ||
|
1411 | c.commit = self._get_commit_or_redirect(commit_id, redirect_after=False) | |
|
1412 | if c.commit is None: | |
|
1413 | c.commit = EmptyCommit(alias=self.rhodecode_vcs_repo.alias) | |
|
1414 | ||
|
1415 | # calculate redirect URL | |
|
1416 | if self.rhodecode_vcs_repo.is_empty(): | |
|
1417 | default_redirect_url = h.route_path( | |
|
1418 | 'repo_summary', repo_name=self.db_repo_name) | |
|
1419 | else: | |
|
1420 | default_redirect_url = h.route_path( | |
|
1421 | 'repo_commit', repo_name=self.db_repo_name, commit_id='tip') | |
|
1422 | ||
|
1423 | if self.rhodecode_vcs_repo.is_empty(): | |
|
1424 | # for empty repository we cannot check for current branch, we rely on | |
|
1425 | # c.commit.branch instead | |
|
1426 | _branch_name = c.commit.branch | |
|
1427 | is_head = True | |
|
1428 | else: | |
|
1429 | _branch_name, _sha_commit_id, is_head = \ | |
|
1430 | self._is_valid_head(commit_id, self.rhodecode_vcs_repo) | |
|
1431 | ||
|
1432 | error = self.forbid_non_head(is_head, f_path, json_mode=True) | |
|
1433 | if error: | |
|
1434 | return { | |
|
1435 | 'error': error, | |
|
1436 | 'redirect_url': default_redirect_url | |
|
1437 | } | |
|
1438 | error = self.check_branch_permission(_branch_name, json_mode=True) | |
|
1439 | if error: | |
|
1440 | return { | |
|
1441 | 'error': error, | |
|
1442 | 'redirect_url': default_redirect_url | |
|
1443 | } | |
|
1444 | ||
|
1445 | c.default_message = (_('Uploaded file via RhodeCode Enterprise')) | |
|
1446 | c.f_path = f_path | |
|
1447 | ||
|
1448 | r_post = self.request.POST | |
|
1449 | ||
|
1450 | message = c.default_message | |
|
1451 | user_message = r_post.getall('message') | |
|
1452 | if isinstance(user_message, list) and user_message: | |
|
1453 | # we take the first from duplicated results if it's not empty | |
|
1454 | message = user_message[0] if user_message[0] else message | |
|
1455 | ||
|
1456 | nodes = {} | |
|
1457 | ||
|
1458 | for file_obj in r_post.getall('files_upload') or []: | |
|
1459 | content = file_obj.file | |
|
1460 | filename = file_obj.filename | |
|
1461 | ||
|
1462 | root_path = f_path | |
|
1463 | pure_path = self.create_pure_path(root_path, filename) | |
|
1464 | node_path = safe_unicode(bytes(pure_path).lstrip('/')) | |
|
1465 | ||
|
1466 | nodes[node_path] = { | |
|
1467 | 'content': content | |
|
1468 | } | |
|
1469 | ||
|
1470 | if not nodes: | |
|
1471 | error = 'missing files' | |
|
1472 | return { | |
|
1473 | 'error': error, | |
|
1474 | 'redirect_url': default_redirect_url | |
|
1475 | } | |
|
1476 | ||
|
1477 | author = self._rhodecode_db_user.full_contact | |
|
1478 | ||
|
1479 | try: | |
|
1480 | commit = ScmModel().create_nodes( | |
|
1481 | user=self._rhodecode_db_user.user_id, | |
|
1482 | repo=self.db_repo, | |
|
1483 | message=message, | |
|
1484 | nodes=nodes, | |
|
1485 | parent_commit=c.commit, | |
|
1486 | author=author, | |
|
1487 | ) | |
|
1488 | if len(nodes) == 1: | |
|
1489 | flash_message = _('Successfully committed {} new files').format(len(nodes)) | |
|
1490 | else: | |
|
1491 | flash_message = _('Successfully committed 1 new file') | |
|
1492 | ||
|
1493 | h.flash(flash_message, category='success') | |
|
1494 | ||
|
1495 | default_redirect_url = h.route_path( | |
|
1496 | 'repo_commit', repo_name=self.db_repo_name, commit_id=commit.raw_id) | |
|
1497 | ||
|
1498 | except NonRelativePathError: | |
|
1499 | log.exception('Non Relative path found') | |
|
1500 | error = _('The location specified must be a relative path and must not ' | |
|
1501 | 'contain .. in the path') | |
|
1502 | h.flash(error, category='warning') | |
|
1503 | ||
|
1504 | return { | |
|
1505 | 'error': error, | |
|
1506 | 'redirect_url': default_redirect_url | |
|
1507 | } | |
|
1508 | except (NodeError, NodeAlreadyExistsError) as e: | |
|
1509 | error = h.escape(e) | |
|
1510 | h.flash(error, category='error') | |
|
1511 | ||
|
1512 | return { | |
|
1513 | 'error': error, | |
|
1514 | 'redirect_url': default_redirect_url | |
|
1515 | } | |
|
1516 | except Exception: | |
|
1517 | log.exception('Error occurred during commit') | |
|
1518 | error = _('Error occurred during commit') | |
|
1519 | h.flash(error, category='error') | |
|
1520 | return { | |
|
1521 | 'error': error, | |
|
1522 | 'redirect_url': default_redirect_url | |
|
1523 | } | |
|
1524 | ||
|
1525 | return { | |
|
1526 | 'error': None, | |
|
1527 | 'redirect_url': default_redirect_url | |
|
1528 | } |
@@ -1939,23 +1939,26 b' def secure_form(form_url, method="POST",' | |||
|
1939 | 1939 | |
|
1940 | 1940 | def dropdownmenu(name, selected, options, enable_filter=False, **attrs): |
|
1941 | 1941 | select_html = select(name, selected, options, **attrs) |
|
1942 | ||
|
1942 | 1943 | select2 = """ |
|
1943 | 1944 | <script> |
|
1944 | 1945 | $(document).ready(function() { |
|
1945 | 1946 | $('#%s').select2({ |
|
1946 | containerCssClass: 'drop-menu', | |
|
1947 | containerCssClass: 'drop-menu %s', | |
|
1947 | 1948 | dropdownCssClass: 'drop-menu-dropdown', |
|
1948 | 1949 | dropdownAutoWidth: true%s |
|
1949 | 1950 | }); |
|
1950 | 1951 | }); |
|
1951 | 1952 | </script> |
|
1952 | 1953 | """ |
|
1954 | ||
|
1953 | 1955 | filter_option = """, |
|
1954 | 1956 | minimumResultsForSearch: -1 |
|
1955 | 1957 | """ |
|
1956 | 1958 | input_id = attrs.get('id') or name |
|
1959 | extra_classes = ' '.join(attrs.pop('extra_classes', [])) | |
|
1957 | 1960 | filter_enabled = "" if enable_filter else filter_option |
|
1958 | select_script = literal(select2 % (input_id, filter_enabled)) | |
|
1961 | select_script = literal(select2 % (input_id, extra_classes, filter_enabled)) | |
|
1959 | 1962 | |
|
1960 | 1963 | return literal(select_html+select_script) |
|
1961 | 1964 |
@@ -818,6 +818,8 b' class ScmModel(BaseModel):' | |||
|
818 | 818 | repo_name=repo.repo_name, repo_alias=scm_instance.alias, |
|
819 | 819 | commit_ids=[tip.raw_id]) |
|
820 | 820 | |
|
821 | return tip | |
|
822 | ||
|
821 | 823 | def delete_nodes(self, user, repo, message, nodes, parent_commit=None, |
|
822 | 824 | author=None, trigger_push_hook=True): |
|
823 | 825 | """ |
@@ -27,7 +27,7 b'' | |||
|
27 | 27 | |
|
28 | 28 | .CodeMirror-gutters { |
|
29 | 29 | border-right: 1px solid #ddd; |
|
30 |
background-color: |
|
|
30 | background-color: white; | |
|
31 | 31 | white-space: nowrap; |
|
32 | 32 | } |
|
33 | 33 | .CodeMirror-linenumbers {} |
@@ -231,6 +231,11 b' form.rcform {' | |||
|
231 | 231 | |
|
232 | 232 | .drop-menu { |
|
233 | 233 | float: left; |
|
234 | ||
|
235 | & + .last-item { | |
|
236 | margin: 0; | |
|
237 | } | |
|
238 | ||
|
234 | 239 | margin: 0 @input-padding 0 0; |
|
235 | 240 | } |
|
236 | 241 |
@@ -277,7 +277,9 b' input.inline[type="file"] {' | |||
|
277 | 277 | // Gists |
|
278 | 278 | #files_data { |
|
279 | 279 | clear: both; //for firefox |
|
280 | } | |
|
280 | padding-top: 10px; | |
|
281 | } | |
|
282 | ||
|
281 | 283 | #gistid { |
|
282 | 284 | margin-right: @padding; |
|
283 | 285 | } |
@@ -1329,7 +1331,7 b' table.integrations {' | |||
|
1329 | 1331 | |
|
1330 | 1332 | #editor_container{ |
|
1331 | 1333 |
|
|
1332 |
|
|
|
1334 | margin: @padding 10px; | |
|
1333 | 1335 | } |
|
1334 | 1336 | } |
|
1335 | 1337 | |
@@ -2063,15 +2065,15 b' BIN_FILENODE = 7' | |||
|
2063 | 2065 | |
|
2064 | 2066 | // Files |
|
2065 | 2067 | .edit-file-title { |
|
2066 | border-bottom: @border-thickness solid @border-default-color; | |
|
2067 | ||
|
2068 | .breadcrumbs { | |
|
2069 | margin-bottom: 0; | |
|
2068 | font-size: 16px; | |
|
2069 | ||
|
2070 | .title-heading { | |
|
2071 | padding: 2px; | |
|
2070 | 2072 | } |
|
2071 | 2073 | } |
|
2072 | 2074 | |
|
2073 | 2075 | .edit-file-fieldset { |
|
2074 |
margin |
|
|
2076 | margin: @sidebarpadding 0; | |
|
2075 | 2077 | |
|
2076 | 2078 | .fieldset { |
|
2077 | 2079 | .left-label { |
@@ -2120,6 +2122,27 b' BIN_FILENODE = 7' | |||
|
2120 | 2122 | margin: 0 0 0 10px; |
|
2121 | 2123 | } |
|
2122 | 2124 | |
|
2125 | .file-upload-transaction-wrapper { | |
|
2126 | margin-top: 57px; | |
|
2127 | clear: both; | |
|
2128 | } | |
|
2129 | ||
|
2130 | .file-upload-transaction-wrapper .error { | |
|
2131 | color: @color5; | |
|
2132 | } | |
|
2133 | ||
|
2134 | .file-upload-transaction { | |
|
2135 | min-height: 200px; | |
|
2136 | padding: 54px; | |
|
2137 | border: 1px solid @grey5; | |
|
2138 | text-align: center; | |
|
2139 | clear: both; | |
|
2140 | } | |
|
2141 | ||
|
2142 | .file-upload-transaction i { | |
|
2143 | font-size: 48px | |
|
2144 | } | |
|
2145 | ||
|
2123 | 2146 | h3.files_location{ |
|
2124 | 2147 | line-height: 2.4em; |
|
2125 | 2148 | } |
@@ -2308,6 +2331,101 b' h3.files_location{' | |||
|
2308 | 2331 | } |
|
2309 | 2332 | |
|
2310 | 2333 | |
|
2334 | .edit-file-fieldset #location, | |
|
2335 | .edit-file-fieldset #filename { | |
|
2336 | display: flex; | |
|
2337 | width: -moz-available; /* WebKit-based browsers will ignore this. */ | |
|
2338 | width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */ | |
|
2339 | width: fill-available; | |
|
2340 | border: 0; | |
|
2341 | } | |
|
2342 | ||
|
2343 | .path-items { | |
|
2344 | display: flex; | |
|
2345 | padding: 0; | |
|
2346 | border: 1px solid #eeeeee; | |
|
2347 | width: 100%; | |
|
2348 | float: left; | |
|
2349 | ||
|
2350 | .breadcrumb-path { | |
|
2351 | line-height: 30px; | |
|
2352 | padding: 0 4px; | |
|
2353 | white-space: nowrap; | |
|
2354 | } | |
|
2355 | ||
|
2356 | .location-path { | |
|
2357 | width: -moz-available; /* WebKit-based browsers will ignore this. */ | |
|
2358 | width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */ | |
|
2359 | width: fill-available; | |
|
2360 | ||
|
2361 | .file-name-input { | |
|
2362 | padding: 0.5em 0; | |
|
2363 | } | |
|
2364 | ||
|
2365 | } | |
|
2366 | ||
|
2367 | ul { | |
|
2368 | display: flex; | |
|
2369 | margin: 0; | |
|
2370 | padding: 0; | |
|
2371 | } | |
|
2372 | li { | |
|
2373 | list-style-type: none; | |
|
2374 | } | |
|
2375 | } | |
|
2376 | ||
|
2377 | .editor-items { | |
|
2378 | height: 40px; | |
|
2379 | margin: 10px 0 -17px 10px; | |
|
2380 | ||
|
2381 | .editor-action { | |
|
2382 | cursor: pointer; | |
|
2383 | } | |
|
2384 | ||
|
2385 | .editor-action.active { | |
|
2386 | border-bottom: 2px solid #5C5C5C; | |
|
2387 | } | |
|
2388 | ||
|
2389 | li { | |
|
2390 | list-style-type: none; | |
|
2391 | } | |
|
2392 | } | |
|
2393 | ||
|
2394 | .edit-file-fieldset .message textarea { | |
|
2395 | border: 1px solid #eeeeee; | |
|
2396 | } | |
|
2397 | ||
|
2398 | #files_data .codeblock { | |
|
2399 | background-color: #F5F5F5; | |
|
2400 | } | |
|
2401 | ||
|
2402 | #editor_preview { | |
|
2403 | background: white; | |
|
2404 | } | |
|
2405 | ||
|
2406 | .show-editor { | |
|
2407 | padding: 10px; | |
|
2408 | background-color: white; | |
|
2409 | ||
|
2410 | } | |
|
2411 | ||
|
2412 | .show-preview { | |
|
2413 | padding: 10px; | |
|
2414 | background-color: white; | |
|
2415 | border-left: 1px solid #eeeeee; | |
|
2416 | } | |
|
2417 | ||
|
2418 | ||
|
2419 | ||
|
2420 | ||
|
2421 | ||
|
2422 | ||
|
2423 | ||
|
2424 | ||
|
2425 | ||
|
2426 | ||
|
2427 | ||
|
2428 | ||
|
2311 | 2429 | // Search |
|
2312 | 2430 | |
|
2313 | 2431 | .search-form{ |
@@ -2577,27 +2695,28 b' form.markup-form {' | |||
|
2577 | 2695 | padding: 20px; |
|
2578 | 2696 | } |
|
2579 | 2697 | |
|
2580 |
.dropzone |
|
|
2698 | .dropzone, | |
|
2699 | .dropzone-pure { | |
|
2581 | 2700 | border: 2px dashed @grey5; |
|
2582 | 2701 | border-radius: 5px; |
|
2583 | 2702 | background: white; |
|
2584 | 2703 | min-height: 200px; |
|
2585 | 2704 | padding: 54px; |
|
2586 | } | |
|
2587 |
. |
|
|
2705 | ||
|
2706 | .dz-message { | |
|
2588 | 2707 | font-weight: 700; |
|
2589 | } | |
|
2590 | ||
|
2591 | .dropzone .dz-message { | |
|
2592 | 2708 | text-align: center; |
|
2593 | 2709 | margin: 2em 0; |
|
2594 | 2710 | } |
|
2595 | 2711 | |
|
2712 | } | |
|
2713 | ||
|
2596 | 2714 | .dz-preview { |
|
2597 |
margin: 10px 0 |
|
|
2715 | margin: 10px 0 !important; | |
|
2598 | 2716 | position: relative; |
|
2599 | 2717 | vertical-align: top; |
|
2600 | 2718 | padding: 10px; |
|
2719 | border-bottom: 1px solid @grey5; | |
|
2601 | 2720 | } |
|
2602 | 2721 | |
|
2603 | 2722 | .dz-filename { |
@@ -2605,6 +2724,10 b' form.markup-form {' | |||
|
2605 | 2724 | float:left; |
|
2606 | 2725 | } |
|
2607 | 2726 | |
|
2727 | .dz-sending { | |
|
2728 | float: right; | |
|
2729 | } | |
|
2730 | ||
|
2608 | 2731 | .dz-response { |
|
2609 | 2732 | clear:both |
|
2610 | 2733 | } |
@@ -2615,4 +2738,6 b' form.markup-form {' | |||
|
2615 | 2738 | |
|
2616 | 2739 | .dz-error-message { |
|
2617 | 2740 | color: @alert2; |
|
2618 | } No newline at end of file | |
|
2741 | padding-top: 10px; | |
|
2742 | clear: both; | |
|
2743 | } |
@@ -149,6 +149,7 b' function registerRCRoutes() {' | |||
|
149 | 149 | pyroutes.register('repo_group_list_data', '/_repo_groups', []); |
|
150 | 150 | pyroutes.register('goto_switcher_data', '/_goto_data', []); |
|
151 | 151 | pyroutes.register('markup_preview', '/_markup_preview', []); |
|
152 | pyroutes.register('file_preview', '/_file_preview', []); | |
|
152 | 153 | pyroutes.register('store_user_session_value', '/_store_session_attr', []); |
|
153 | 154 | pyroutes.register('journal', '/_admin/journal', []); |
|
154 | 155 | pyroutes.register('journal_rss', '/_admin/journal/rss', []); |
@@ -204,7 +204,12 b' var CodeMirrorCompleteAfter = function(c' | |||
|
204 | 204 | }; |
|
205 | 205 | |
|
206 | 206 | var initCodeMirror = function(textAreadId, resetUrl, focus, options) { |
|
207 | if (textAreadId.substr(0,1) === "#"){ | |
|
208 | var ta = $(textAreadId).get(0); | |
|
209 | }else { | |
|
207 | 210 | var ta = $('#' + textAreadId).get(0); |
|
211 | } | |
|
212 | ||
|
208 | 213 | if (focus === undefined) { |
|
209 | 214 | focus = true; |
|
210 | 215 | } |
@@ -644,18 +649,6 b' var fillCodeMirrorOptions = function(tar' | |||
|
644 | 649 | } |
|
645 | 650 | }; |
|
646 | 651 | |
|
647 | var CodeMirrorPreviewEnable = function(edit_mode) { | |
|
648 | // in case it a preview enabled mode enable the button | |
|
649 | if (['markdown', 'rst', 'gfm'].indexOf(edit_mode) !== -1) { | |
|
650 | $('#render_preview').removeClass('hidden'); | |
|
651 | } | |
|
652 | else { | |
|
653 | if (!$('#render_preview').hasClass('hidden')) { | |
|
654 | $('#render_preview').addClass('hidden'); | |
|
655 | } | |
|
656 | } | |
|
657 | }; | |
|
658 | ||
|
659 | 652 | |
|
660 | 653 | /* markup form */ |
|
661 | 654 | (function(mod) { |
@@ -409,3 +409,109 b' var showAuthors = function(elem, annotat' | |||
|
409 | 409 | $('#file_authors_title').html(_gettext('All Authors')) |
|
410 | 410 | }) |
|
411 | 411 | }; |
|
412 | ||
|
413 | ||
|
414 | (function (mod) { | |
|
415 | ||
|
416 | if (typeof exports == "object" && typeof module == "object") { | |
|
417 | // CommonJS | |
|
418 | module.exports = mod(); | |
|
419 | } else { | |
|
420 | // Plain browser env | |
|
421 | (this || window).FileEditor = mod(); | |
|
422 | } | |
|
423 | ||
|
424 | })(function () { | |
|
425 | "use strict"; | |
|
426 | ||
|
427 | function FileEditor(textAreaElement, options) { | |
|
428 | if (!(this instanceof FileEditor)) { | |
|
429 | return new FileEditor(textAreaElement, options); | |
|
430 | } | |
|
431 | // bind the element instance to our Form | |
|
432 | var te = $(textAreaElement).get(0); | |
|
433 | if (te !== undefined) { | |
|
434 | te.FileEditor = this; | |
|
435 | } | |
|
436 | ||
|
437 | this.modes_select = '#set_mode'; | |
|
438 | this.filename_selector = '#filename'; | |
|
439 | this.commit_btn_selector = '#commit_btn'; | |
|
440 | this.line_wrap_selector = '#line_wrap'; | |
|
441 | this.editor_preview_selector = '#editor_preview'; | |
|
442 | ||
|
443 | if (te !== undefined) { | |
|
444 | this.cm = initCodeMirror(textAreaElement, null, false); | |
|
445 | } | |
|
446 | ||
|
447 | // FUNCTIONS and helpers | |
|
448 | var self = this; | |
|
449 | ||
|
450 | this.submitHandler = function() { | |
|
451 | $(self.commit_btn_selector).on('click', function(e) { | |
|
452 | ||
|
453 | var filename = $(self.filename_selector).val(); | |
|
454 | if (filename === "") { | |
|
455 | alert("Missing filename"); | |
|
456 | e.preventDefault(); | |
|
457 | } | |
|
458 | ||
|
459 | var button = $(this); | |
|
460 | if (button.hasClass('clicked')) { | |
|
461 | button.attr('disabled', true); | |
|
462 | } else { | |
|
463 | button.addClass('clicked'); | |
|
464 | } | |
|
465 | }); | |
|
466 | }; | |
|
467 | this.submitHandler(); | |
|
468 | ||
|
469 | // on select line wraps change the editor | |
|
470 | this.lineWrapHandler = function () { | |
|
471 | $(self.line_wrap_selector).on('change', function (e) { | |
|
472 | var selected = e.currentTarget; | |
|
473 | var line_wraps = {'on': true, 'off': false}[selected.value]; | |
|
474 | setCodeMirrorLineWrap(self.cm, line_wraps) | |
|
475 | }); | |
|
476 | }; | |
|
477 | this.lineWrapHandler(); | |
|
478 | ||
|
479 | ||
|
480 | this.showPreview = function () { | |
|
481 | ||
|
482 | var _text = self.cm.getValue(); | |
|
483 | var _file_path = $(self.filename_selector).val(); | |
|
484 | if (_text && _file_path) { | |
|
485 | $('.show-preview').addClass('active'); | |
|
486 | $('.show-editor').removeClass('active'); | |
|
487 | ||
|
488 | $(self.editor_preview_selector).show(); | |
|
489 | $(self.cm.getWrapperElement()).hide(); | |
|
490 | ||
|
491 | ||
|
492 | var post_data = {'text': _text, 'file_path': _file_path, 'csrf_token': CSRF_TOKEN}; | |
|
493 | $(self.editor_preview_selector).html(_gettext('Loading ...')); | |
|
494 | ||
|
495 | var url = pyroutes.url('file_preview'); | |
|
496 | ||
|
497 | ajaxPOST(url, post_data, function (o) { | |
|
498 | $(self.editor_preview_selector).html(o); | |
|
499 | }) | |
|
500 | } | |
|
501 | ||
|
502 | }; | |
|
503 | ||
|
504 | this.showEditor = function () { | |
|
505 | $(self.editor_preview_selector).hide(); | |
|
506 | $('.show-editor').addClass('active'); | |
|
507 | $('.show-preview').removeClass('active'); | |
|
508 | ||
|
509 | $(self.cm.getWrapperElement()).show(); | |
|
510 | }; | |
|
511 | ||
|
512 | ||
|
513 | } | |
|
514 | ||
|
515 | return FileEditor; | |
|
516 | }); | |
|
517 |
@@ -1,7 +1,7 b'' | |||
|
1 | 1 | <%inherit file="/base/base.mako"/> |
|
2 | 2 | |
|
3 | 3 | <%def name="title()"> |
|
4 |
${_(' |
|
|
4 | ${_('{} Files Add').format(c.repo_name)} | |
|
5 | 5 | %if c.rhodecode_name: |
|
6 | 6 | · ${h.branding(c.rhodecode_name)} |
|
7 | 7 | %endif |
@@ -11,58 +11,60 b'' | |||
|
11 | 11 | ${self.menu_items(active='repositories')} |
|
12 | 12 | </%def> |
|
13 | 13 | |
|
14 | <%def name="breadcrumbs_links()"> | |
|
15 | ${_('Add new file')} @ ${h.show_id(c.commit)} ${_('Branch')}: ${c.commit.branch} | |
|
16 | </%def> | |
|
14 | <%def name="breadcrumbs_links()"></%def> | |
|
17 | 15 | |
|
18 | 16 | <%def name="menu_bar_subnav()"> |
|
19 | 17 | ${self.repo_menu(active='files')} |
|
20 | 18 | </%def> |
|
21 | 19 | |
|
22 | 20 | <%def name="main()"> |
|
21 | ||
|
23 | 22 | <div class="box"> |
|
24 | 23 | |
|
25 | 24 | <div class="edit-file-title"> |
|
26 | ${self.breadcrumbs()} | |
|
25 | <span class="title-heading">${_('Add new file')} @ <code>${h.show_id(c.commit)}</code></span> | |
|
26 | <span class="tag branchtag"><i class="icon-branch"></i> ${c.commit.branch}</span> | |
|
27 | 27 | </div> |
|
28 | 28 | |
|
29 |
${h.secure_form(h.route_path('repo_files_create_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', |
|
|
29 | ${h.secure_form(h.route_path('repo_files_create_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)} | |
|
30 | 30 | <div class="edit-file-fieldset"> |
|
31 |
<div class=" |
|
|
32 | <div id="destination-label" class="left-label"> | |
|
33 | ${_('Path')}: | |
|
34 | </div> | |
|
35 | <div class="right-content"> | |
|
31 | <div class="path-items"> | |
|
32 | <ul> | |
|
33 | <li class="breadcrumb-path"> | |
|
36 | 34 | <div> |
|
37 | ${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.f_path, request.GET.get('at'))} / | |
|
38 | <input type="input-small" value="${c.f_path}" size="46" name="location" id="location"> | |
|
35 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path='')}"><i class="icon-home"></i></a> / | |
|
36 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path)}">${c.f_path}</a> ${('/' if c.f_path else '')} | |
|
39 | 37 | </div> |
|
40 |
</ |
|
|
41 | </div> | |
|
42 | <div id="filename_container" class="fieldset"> | |
|
43 | <div class="filename-label left-label"> | |
|
44 | ${_('Filename')}: | |
|
45 | </div> | |
|
46 | <div class="right-content"> | |
|
47 | <input class="input-small" type="text" value="" size="46" name="filename" id="filename"> | |
|
48 | ||
|
49 | </div> | |
|
38 | </li> | |
|
39 | <li class="location-path"> | |
|
40 | <input class="file-name-input input-small" type="text" value="" name="filename" id="filename" placeholder="${_('Filename e.g example.py, or docs/readme.md')}"> | |
|
41 | </li> | |
|
42 | </ul> | |
|
50 | 43 | </div> |
|
51 | 44 | |
|
52 | 45 | </div> |
|
53 | 46 | |
|
54 | 47 | <div class="table"> |
|
55 | 48 | <div id="files_data"> |
|
49 | ||
|
56 | 50 | <div id="codeblock" class="codeblock"> |
|
57 | <div class="code-header form" id="set_mode_header"> | |
|
58 | <div class="fields"> | |
|
51 | <div class="editor-items"> | |
|
52 | <div class="editor-action active show-editor pull-left" onclick="fileEditor.showEditor(); return false"> | |
|
53 | ${_('Edit')} | |
|
54 | </div> | |
|
55 | ||
|
56 | <div class="editor-action show-preview pull-left" onclick="fileEditor.showPreview(); return false"> | |
|
57 | ${_('Preview')} | |
|
58 | </div> | |
|
59 | ||
|
60 | <div class="pull-right"> | |
|
61 | ${h.dropdownmenu('line_wrap', 'off', [('on', _('Line wraps on')), ('off', _('line wraps off'))], extra_classes=['last-item'])} | |
|
62 | </div> | |
|
63 | <div class="pull-right"> | |
|
59 | 64 | ${h.dropdownmenu('set_mode','plain',[('plain',_('plain'))],enable_filter=True)} |
|
60 | <label for="line_wrap">${_('line wraps')}</label> | |
|
61 | ${h.dropdownmenu('line_wrap', 'off', [('on', _('on')), ('off', _('off')),])} | |
|
62 | ||
|
63 | <div id="render_preview" class="btn btn-small preview hidden" >${_('Preview')}</div> | |
|
64 | 65 | </div> |
|
65 | 66 | </div> |
|
67 | ||
|
66 | 68 | <div id="editor_container"> |
|
67 | 69 | <pre id="editor_pre"></pre> |
|
68 | 70 | <textarea id="editor" name="content" ></textarea> |
@@ -74,109 +76,35 b'' | |||
|
74 | 76 | |
|
75 | 77 | <div class="edit-file-fieldset"> |
|
76 | 78 | <div class="fieldset"> |
|
77 | <div id="commit-message-label" class="commit-message-label left-label"> | |
|
78 | ${_('Commit Message')}: | |
|
79 | </div> | |
|
80 | <div class="right-content"> | |
|
81 | 79 |
|
|
82 | 80 |
|
|
83 | 81 |
|
|
84 | 82 |
|
|
85 | </div> | |
|
86 | <div class="pull-right"> | |
|
87 | ${h.reset('reset',_('Cancel'),class_="btn btn-small")} | |
|
83 | <div class="pull-left"> | |
|
88 | 84 | ${h.submit('commit_btn',_('Commit changes'),class_="btn btn-small btn-success")} |
|
89 | 85 | </div> |
|
90 | 86 | </div> |
|
91 | 87 | ${h.end_form()} |
|
92 | 88 | </div> |
|
89 | ||
|
93 | 90 | <script type="text/javascript"> |
|
94 | 91 | |
|
95 |
$( |
|
|
96 | var button = $(this); | |
|
97 | if (button.hasClass('clicked')) { | |
|
98 | button.attr('disabled', true); | |
|
99 | } else { | |
|
100 | button.addClass('clicked'); | |
|
101 | } | |
|
102 | }); | |
|
103 | ||
|
104 | var hide_upload = function(){ | |
|
105 | $('#files_data').show(); | |
|
106 | $('#upload_file_container').hide(); | |
|
107 | $('#filename_container').show(); | |
|
108 | }; | |
|
109 | ||
|
110 | $('#file_enable').on('click', function(e){ | |
|
111 | e.preventDefault(); | |
|
112 | hide_upload(); | |
|
113 | }); | |
|
114 | ||
|
115 | var renderer = ""; | |
|
116 | var reset_url = "${h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}"; | |
|
117 | var myCodeMirror = initCodeMirror('editor', reset_url, false); | |
|
118 | ||
|
92 | $(document).ready(function () { | |
|
119 | 93 | var modes_select = $('#set_mode'); |
|
94 | var filename_selector = '#filename'; | |
|
120 | 95 | fillCodeMirrorOptions(modes_select); |
|
121 | 96 | |
|
122 | var filename_selector = '#filename'; | |
|
123 | var callback = function(filename, mimetype, mode){ | |
|
124 | CodeMirrorPreviewEnable(mode); | |
|
125 | }; | |
|
97 | fileEditor = new FileEditor('#editor'); | |
|
98 | ||
|
126 | 99 | // on change of select field set mode |
|
127 | setCodeMirrorModeFromSelect( | |
|
128 | modes_select, filename_selector, myCodeMirror, callback); | |
|
100 | setCodeMirrorModeFromSelect(modes_select, filename_selector, fileEditor.cm, null); | |
|
129 | 101 | |
|
130 | 102 | // on entering the new filename set mode, from given extension |
|
131 | setCodeMirrorModeFromInput( | |
|
132 | modes_select, filename_selector, myCodeMirror, callback); | |
|
133 | ||
|
134 | // if the file is renderable set line wraps automatically | |
|
135 | if (renderer !== ""){ | |
|
136 | var line_wrap = 'on'; | |
|
137 | $($('#line_wrap option[value="'+line_wrap+'"]')[0]).attr("selected", "selected"); | |
|
138 | setCodeMirrorLineWrap(myCodeMirror, true); | |
|
139 | } | |
|
140 | ||
|
141 | // on select line wraps change the editor | |
|
142 | $('#line_wrap').on('change', function(e){ | |
|
143 | var selected = e.currentTarget; | |
|
144 | var line_wraps = {'on': true, 'off': false}[selected.value]; | |
|
145 | setCodeMirrorLineWrap(myCodeMirror, line_wraps) | |
|
146 | }); | |
|
147 | ||
|
148 | // render preview/edit button | |
|
149 | $('#render_preview').on('click', function(e){ | |
|
150 | if($(this).hasClass('preview')){ | |
|
151 | $(this).removeClass('preview'); | |
|
152 | $(this).html("${_('Edit')}"); | |
|
153 | $('#editor_preview').show(); | |
|
154 | $(myCodeMirror.getWrapperElement()).hide(); | |
|
103 | setCodeMirrorModeFromInput(modes_select, filename_selector, fileEditor.cm, null); | |
|
155 | 104 | |
|
156 | var possible_renderer = { | |
|
157 | 'rst':'rst', | |
|
158 | 'markdown':'markdown', | |
|
159 | 'gfm': 'markdown'}[myCodeMirror.getMode().name]; | |
|
160 | var _text = myCodeMirror.getValue(); | |
|
161 | var _renderer = possible_renderer || DEFAULT_RENDERER; | |
|
162 | var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN}; | |
|
163 | $('#editor_preview').html(_gettext('Loading ...')); | |
|
164 | var url = pyroutes.url('repo_commit_comment_preview', | |
|
165 | {'repo_name': '${c.repo_name}', | |
|
166 | 'commit_id': '${c.commit.raw_id}'}); | |
|
105 | $('#filename').focus(); | |
|
167 | 106 | |
|
168 | ajaxPOST(url, post_data, function(o){ | |
|
169 | $('#editor_preview').html(o); | |
|
170 | }) | |
|
171 | } | |
|
172 | else{ | |
|
173 | $(this).addClass('preview'); | |
|
174 | $(this).html("${_('Preview')}"); | |
|
175 | $('#editor_preview').hide(); | |
|
176 | $(myCodeMirror.getWrapperElement()).show(); | |
|
177 | } | |
|
178 | 107 | }); |
|
179 | $('#filename').focus(); | |
|
180 | 108 | |
|
181 | 109 | </script> |
|
182 | 110 | </%def> |
@@ -1,7 +1,7 b'' | |||
|
1 | 1 | <%inherit file="/base/base.mako"/> |
|
2 | 2 | |
|
3 | 3 | <%def name="title()"> |
|
4 |
${_(' |
|
|
4 | ${_('{} Files Delete').format(c.repo_name)} | |
|
5 | 5 | %if c.rhodecode_name: |
|
6 | 6 | · ${h.branding(c.rhodecode_name)} |
|
7 | 7 | %endif |
@@ -11,29 +11,36 b'' | |||
|
11 | 11 | ${self.menu_items(active='repositories')} |
|
12 | 12 | </%def> |
|
13 | 13 | |
|
14 | <%def name="breadcrumbs_links()"> | |
|
15 | ${_('Delete file')} @ ${h.show_id(c.commit)} | |
|
16 | </%def> | |
|
14 | <%def name="breadcrumbs_links()"></%def> | |
|
17 | 15 | |
|
18 | 16 | <%def name="menu_bar_subnav()"> |
|
19 | 17 | ${self.repo_menu(active='files')} |
|
20 | 18 | </%def> |
|
21 | 19 | |
|
22 | 20 | <%def name="main()"> |
|
21 | ||
|
23 | 22 | <div class="box"> |
|
23 | ||
|
24 | 24 | <div class="edit-file-title"> |
|
25 | ${self.breadcrumbs()} | |
|
25 | <span class="title-heading">${_('Delete file')} @ <code>${h.show_id(c.commit)}</code></span> | |
|
26 | <span class="tag branchtag"><i class="icon-branch"></i> ${c.commit.branch}</span> | |
|
26 | 27 | </div> |
|
27 | ${h.secure_form(h.route_path('repo_files_delete_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', class_="form-horizontal", request=request)} | |
|
28 | ||
|
29 | ${h.secure_form(h.route_path('repo_files_delete_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)} | |
|
28 | 30 | <div class="edit-file-fieldset"> |
|
29 |
<div class=" |
|
|
30 | <div id="destination-label" class="left-label"> | |
|
31 |
|
|
|
31 | <div class="path-items"> | |
|
32 | <li class="breadcrumb-path"> | |
|
33 | <div> | |
|
34 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path='')}"><i class="icon-home"></i></a> / | |
|
35 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.file.dir_path)}">${c.file.dir_path}</a> ${('/' if c.file.dir_path else '')} | |
|
32 | 36 | </div> |
|
33 | <div class="right-content"> | |
|
34 | <span id="path-breadcrumbs">${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.f_path, request.GET.get('at'))}</span> | |
|
37 | </li> | |
|
38 | <li class="location-path"> | |
|
39 | <input type="hidden" value="${c.f_path}" name="root_path"> | |
|
40 | <input class="file-name-input input-small" type="text" value="${c.file.name}" name="filename" id="filename" disabled="disabled"> | |
|
41 | </li> | |
|
35 | 42 |
|
|
36 | </div> | |
|
43 | ||
|
37 | 44 | </div> |
|
38 | 45 | |
|
39 | 46 | <div id="codeblock" class="codeblock delete-file-preview"> |
@@ -53,20 +60,26 b'' | |||
|
53 | 60 | |
|
54 | 61 | <div class="edit-file-fieldset"> |
|
55 | 62 | <div class="fieldset"> |
|
56 | <div id="commit-message-label" class="commit-message-label left-label"> | |
|
57 | ${_('Commit Message')}: | |
|
58 | </div> | |
|
59 | <div class="right-content"> | |
|
60 | 63 |
|
|
61 | 64 |
|
|
62 | 65 |
|
|
63 | 66 |
|
|
64 | </div> | |
|
65 | <div class="pull-right"> | |
|
66 | ${h.reset('reset',_('Cancel'),class_="btn btn-small btn-danger")} | |
|
67 | ${h.submit('commit',_('Delete File'),class_="btn btn-small btn-danger-action")} | |
|
67 | <div class="pull-left"> | |
|
68 | ${h.submit('commit',_('Commit changes'),class_="btn btn-small btn-danger-action")} | |
|
68 | 69 | </div> |
|
69 | 70 | </div> |
|
70 | 71 | ${h.end_form()} |
|
71 | 72 | </div> |
|
73 | ||
|
74 | ||
|
75 | <script type="text/javascript"> | |
|
76 | ||
|
77 | $(document).ready(function () { | |
|
78 | ||
|
79 | fileEditor = new FileEditor('#editor'); | |
|
80 | ||
|
81 | }); | |
|
82 | ||
|
83 | </script> | |
|
84 | ||
|
72 | 85 | </%def> |
@@ -1,7 +1,7 b'' | |||
|
1 | 1 | <%inherit file="/base/base.mako"/> |
|
2 | 2 | |
|
3 | 3 | <%def name="title()"> |
|
4 |
${_(' |
|
|
4 | ${_('{} Files Edit').format(c.repo_name)} | |
|
5 | 5 | %if c.rhodecode_name: |
|
6 | 6 | · ${h.branding(c.rhodecode_name)} |
|
7 | 7 | %endif |
@@ -11,77 +11,61 b'' | |||
|
11 | 11 | ${self.menu_items(active='repositories')} |
|
12 | 12 | </%def> |
|
13 | 13 | |
|
14 | <%def name="breadcrumbs_links()"> | |
|
15 | ${_('Edit file')} @ ${h.show_id(c.commit)} | |
|
16 | </%def> | |
|
14 | <%def name="breadcrumbs_links()"></%def> | |
|
17 | 15 | |
|
18 | 16 | <%def name="menu_bar_subnav()"> |
|
19 | 17 | ${self.repo_menu(active='files')} |
|
20 | 18 | </%def> |
|
21 | 19 | |
|
22 | 20 | <%def name="main()"> |
|
23 | <% renderer = h.renderer_from_filename(c.f_path)%> | |
|
21 | ||
|
24 | 22 | <div class="box"> |
|
23 | ||
|
25 | 24 | <div class="edit-file-title"> |
|
26 | ${self.breadcrumbs()} | |
|
25 | <span class="title-heading">${_('Edit file')} @ <code>${h.show_id(c.commit)}</code></span> | |
|
26 | <span class="tag branchtag"><i class="icon-branch"></i> ${c.commit.branch}</span> | |
|
27 | 27 | </div> |
|
28 | ||
|
29 | ${h.secure_form(h.route_path('repo_files_update_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)} | |
|
28 | 30 | <div class="edit-file-fieldset"> |
|
29 |
<div class=" |
|
|
30 | <div id="destination-label" class="left-label"> | |
|
31 | ${_('Path')}: | |
|
31 | <div class="path-items"> | |
|
32 | <ul> | |
|
33 | <li class="breadcrumb-path"> | |
|
34 | <div> | |
|
35 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path='')}"><i class="icon-home"></i></a> / | |
|
36 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.file.dir_path)}">${c.file.dir_path}</a> ${('/' if c.file.dir_path else '')} | |
|
32 | 37 | </div> |
|
33 | <div class="right-content"> | |
|
34 | <div id="specify-custom-path-container"> | |
|
35 | <span id="path-breadcrumbs">${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.f_path, request.GET.get('at'))}</span> | |
|
38 | </li> | |
|
39 | <li class="location-path"> | |
|
40 | <input type="hidden" value="${c.f_path}" name="root_path"> | |
|
41 | <input class="file-name-input input-small" type="text" value="${c.file.name}" name="filename" id="filename" placeholder="${_('Filename e.g example.py, or docs/readme.md')}"> | |
|
42 | </li> | |
|
43 | </ul> | |
|
36 | 44 |
|
|
37 | </div> | |
|
38 | </div> | |
|
45 | ||
|
39 | 46 | </div> |
|
40 | 47 | |
|
41 | 48 | <div class="table"> |
|
42 | ${h.secure_form(h.route_path('repo_files_update_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', request=request)} | |
|
49 | <div id="files_data"> | |
|
50 | ||
|
43 | 51 |
<div id="codeblock" class="codeblock" |
|
44 |
<div class=" |
|
|
45 | <div class="stats"> | |
|
46 | <i class="icon-file"></i> | |
|
47 | <span class="item">${h.link_to("r%s:%s" % (c.file.commit.idx,h.short_id(c.file.commit.raw_id)),h.route_path('repo_commit',repo_name=c.repo_name,commit_id=c.file.commit.raw_id))}</span> | |
|
48 | <span class="item">${h.format_byte_size_binary(c.file.size)}</span> | |
|
49 | <span class="item last">${c.file.mimetype}</span> | |
|
50 | <div class="buttons"> | |
|
51 | <a class="btn btn-mini" href="${h.route_path('repo_commits_file',repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path)}"> | |
|
52 | <i class="icon-time"></i> ${_('history')} | |
|
53 | </a> | |
|
52 | <div class="editor-items"> | |
|
53 | <div class="editor-action active show-editor pull-left" onclick="fileEditor.showEditor(); return false"> | |
|
54 | ${_('Edit')} | |
|
55 | </div> | |
|
54 | 56 |
|
|
55 | % if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name): | |
|
56 | % if not c.file.is_binary: | |
|
57 |
|
|
|
58 | ${h.link_to(_('source'), h.route_path('repo_files', repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path),class_="btn btn-mini")} | |
|
59 | %else: | |
|
60 | ${h.link_to(_('annotation'),h.route_path('repo_files:annotated',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path),class_="btn btn-mini")} | |
|
61 | %endif | |
|
57 | <div class="editor-action show-preview pull-left" onclick="fileEditor.showPreview(); return false"> | |
|
58 | ${_('Preview')} | |
|
59 | </div> | |
|
62 | 60 | |
|
63 | <a class="btn btn-mini" href="${h.route_path('repo_file_raw',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}"> | |
|
64 | ${_('raw')} | |
|
65 |
|
|
|
66 | <a class="btn btn-mini" href="${h.route_path('repo_file_download',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}"> | |
|
67 | <i class="icon-archive"></i> ${_('download')} | |
|
68 | </a> | |
|
69 | % endif | |
|
70 | % endif | |
|
61 | <div class="pull-right"> | |
|
62 | ${h.dropdownmenu('line_wrap', 'off', [('on', _('Line wraps on')), ('off', _('line wraps off')),])} | |
|
63 | </div> | |
|
64 | <div class="pull-right"> | |
|
65 | ${h.dropdownmenu('set_mode','plain',[('plain', _('plain'))],enable_filter=True)} | |
|
71 | 66 | </div> |
|
72 | 67 | </div> |
|
73 | <div class="form"> | |
|
74 | <label for="set_mode">${_('Editing file')}:</label> | |
|
75 | ${'%s /' % c.file.dir_path if c.file.dir_path else c.file.dir_path} | |
|
76 | <input id="filename" type="text" name="filename" value="${c.file.name}"> | |
|
77 | 68 | |
|
78 | ${h.dropdownmenu('set_mode','plain',[('plain',_('plain'))],enable_filter=True)} | |
|
79 | <label for="line_wrap">${_('line wraps')}</label> | |
|
80 | ${h.dropdownmenu('line_wrap', 'off', [('on', _('on')), ('off', _('off')),])} | |
|
81 | ||
|
82 | <div id="render_preview" class="btn btn-small preview hidden">${_('Preview')}</div> | |
|
83 | </div> | |
|
84 | </div> | |
|
85 | 69 | <div id="editor_container"> |
|
86 | 70 | <pre id="editor_pre"></pre> |
|
87 | 71 | <textarea id="editor" name="content" >${h.escape(c.file.content)|n}</textarea> |
@@ -89,106 +73,48 b'' | |||
|
89 | 73 | </div> |
|
90 | 74 | </div> |
|
91 | 75 | </div> |
|
76 | </div> | |
|
92 | 77 | |
|
93 | 78 | <div class="edit-file-fieldset"> |
|
94 | 79 | <div class="fieldset"> |
|
95 | <div id="commit-message-label" class="commit-message-label left-label"> | |
|
96 | ${_('Commit Message')}: | |
|
97 | </div> | |
|
98 | <div class="right-content"> | |
|
99 | 80 |
|
|
100 | 81 |
|
|
101 | 82 |
|
|
102 | 83 |
|
|
103 | </div> | |
|
104 | <div class="pull-right"> | |
|
105 | ${h.reset('reset',_('Cancel'),class_="btn btn-small")} | |
|
106 | ${h.submit('commit',_('Commit changes'),class_="btn btn-small btn-success")} | |
|
84 | <div class="pull-left"> | |
|
85 | ${h.submit('commit_btn',_('Commit changes'), class_="btn btn-small btn-success")} | |
|
107 | 86 | </div> |
|
108 | 87 | </div> |
|
109 | 88 | ${h.end_form()} |
|
110 | 89 | </div> |
|
111 | 90 | |
|
112 | 91 | <script type="text/javascript"> |
|
92 | ||
|
113 | 93 | $(document).ready(function(){ |
|
114 | var renderer = "${renderer}"; | |
|
115 | var reset_url = "${h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.file.path)}"; | |
|
116 | var myCodeMirror = initCodeMirror('editor', reset_url); | |
|
117 | ||
|
118 | 94 | var modes_select = $('#set_mode'); |
|
95 | var filename_selector = '#filename'; | |
|
119 | 96 | fillCodeMirrorOptions(modes_select); |
|
120 | 97 | |
|
98 | fileEditor = new FileEditor('#editor'); | |
|
99 | ||
|
121 | 100 | // try to detect the mode based on the file we edit |
|
122 | var mimetype = "${c.file.mimetype}"; | |
|
123 | var detected_mode = detectCodeMirrorMode( | |
|
124 | "${c.file.name}", mimetype); | |
|
101 | var detected_mode = detectCodeMirrorMode("${c.file.name}", "${c.file.mimetype}"); | |
|
125 | 102 | |
|
126 | 103 | if(detected_mode){ |
|
127 |
setCodeMirrorMode( |
|
|
128 | $(modes_select).select2("val", mimetype); | |
|
129 | $(modes_select).change(); | |
|
130 | setCodeMirrorMode(myCodeMirror, detected_mode); | |
|
104 | setCodeMirrorMode(fileEditor.cm, detected_mode); | |
|
105 | ||
|
106 | var mimetype = $(modes_select).find("option[mode={0}]".format(detected_mode)).val(); | |
|
107 | $(modes_select).select2("val", mimetype).trigger('change'); | |
|
131 | 108 | } |
|
132 | 109 | |
|
133 | var filename_selector = '#filename'; | |
|
134 | var callback = function(filename, mimetype, mode){ | |
|
135 | CodeMirrorPreviewEnable(mode); | |
|
136 | }; | |
|
137 | 110 | // on change of select field set mode |
|
138 | setCodeMirrorModeFromSelect( | |
|
139 | modes_select, filename_selector, myCodeMirror, callback); | |
|
111 | setCodeMirrorModeFromSelect(modes_select, filename_selector, fileEditor.cm, null); | |
|
140 | 112 | |
|
141 | 113 | // on entering the new filename set mode, from given extension |
|
142 | setCodeMirrorModeFromInput( | |
|
143 | modes_select, filename_selector, myCodeMirror, callback); | |
|
114 | setCodeMirrorModeFromInput(modes_select, filename_selector, fileEditor.cm, null); | |
|
144 | 115 | |
|
145 | // if the file is renderable set line wraps automatically | |
|
146 | if (renderer !== ""){ | |
|
147 | var line_wrap = 'on'; | |
|
148 | $($('#line_wrap option[value="'+line_wrap+'"]')[0]).attr("selected", "selected"); | |
|
149 | setCodeMirrorLineWrap(myCodeMirror, true); | |
|
150 | } | |
|
151 | // on select line wraps change the editor | |
|
152 | $('#line_wrap').on('change', function(e){ | |
|
153 | var selected = e.currentTarget; | |
|
154 | var line_wraps = {'on': true, 'off': false}[selected.value]; | |
|
155 | setCodeMirrorLineWrap(myCodeMirror, line_wraps) | |
|
156 | 116 |
|
|
157 | 117 | |
|
158 | // render preview/edit button | |
|
159 | if (mimetype === 'text/x-rst' || mimetype === 'text/plain') { | |
|
160 | $('#render_preview').removeClass('hidden'); | |
|
161 | } | |
|
162 | $('#render_preview').on('click', function(e){ | |
|
163 | if($(this).hasClass('preview')){ | |
|
164 | $(this).removeClass('preview'); | |
|
165 | $(this).html("${_('Edit')}"); | |
|
166 | $('#editor_preview').show(); | |
|
167 | $(myCodeMirror.getWrapperElement()).hide(); | |
|
168 | 118 | |
|
169 | var possible_renderer = { | |
|
170 | 'rst':'rst', | |
|
171 | 'markdown':'markdown', | |
|
172 | 'gfm': 'markdown'}[myCodeMirror.getMode().name]; | |
|
173 | var _text = myCodeMirror.getValue(); | |
|
174 | var _renderer = possible_renderer || DEFAULT_RENDERER; | |
|
175 | var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN}; | |
|
176 | $('#editor_preview').html(_gettext('Loading ...')); | |
|
177 | var url = pyroutes.url('repo_commit_comment_preview', | |
|
178 | {'repo_name': '${c.repo_name}', | |
|
179 | 'commit_id': '${c.commit.raw_id}'}); | |
|
180 | ajaxPOST(url, post_data, function(o){ | |
|
181 | $('#editor_preview').html(o); | |
|
182 | }) | |
|
183 | } | |
|
184 | else{ | |
|
185 | $(this).addClass('preview'); | |
|
186 | $(this).html("${_('Preview')}"); | |
|
187 | $('#editor_preview').hide(); | |
|
188 | $(myCodeMirror.getWrapperElement()).show(); | |
|
189 | } | |
|
190 | }); | |
|
191 | ||
|
192 | }) | |
|
193 | 119 | </script> |
|
194 | 120 | </%def> |
@@ -23,17 +23,17 b'' | |||
|
23 | 23 | |
|
24 | 24 | %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name): |
|
25 | 25 | ## on branch head, can edit files |
|
26 |
%if c.on_branch_head and c.branch_or_raw_id |
|
|
26 | %if c.on_branch_head and c.branch_or_raw_id: | |
|
27 | 27 | ## binary files are delete only |
|
28 | 28 | % if c.file.is_binary: |
|
29 | 29 | ${h.link_to(_('Edit'), '#Edit', class_="btn btn-default disabled tooltip", title=_('Editing binary files not allowed'))} |
|
30 |
${h.link_to(_('Delete'), h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path |
|
|
30 | ${h.link_to(_('Delete'), h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path),class_="btn btn-danger")} | |
|
31 | 31 | % else: |
|
32 |
<a class="btn btn-default" href="${h.route_path('repo_files_edit_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path |
|
|
32 | <a class="btn btn-default" href="${h.route_path('repo_files_edit_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path)}"> | |
|
33 | 33 | ${_('Edit on branch: ')}<code>${c.branch_name}</code> |
|
34 | 34 | </a> |
|
35 | 35 | |
|
36 |
<a class="btn btn-danger" href="${h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path |
|
|
36 | <a class="btn btn-danger" href="${h.route_path('repo_files_remove_file',repo_name=c.repo_name,commit_id=c.branch_or_raw_id,f_path=c.f_path)}"> | |
|
37 | 37 | ${_('Delete')} |
|
38 | 38 | </a> |
|
39 | 39 | % endif |
@@ -1,7 +1,7 b'' | |||
|
1 | 1 | <%inherit file="/base/base.mako"/> |
|
2 | 2 | |
|
3 | 3 | <%def name="title()"> |
|
4 |
${_(' |
|
|
4 | ${_('{} Files Upload').format(c.repo_name)} | |
|
5 | 5 | %if c.rhodecode_name: |
|
6 | 6 | · ${h.branding(c.rhodecode_name)} |
|
7 | 7 | %endif |
@@ -11,180 +11,197 b'' | |||
|
11 | 11 | ${self.menu_items(active='repositories')} |
|
12 | 12 | </%def> |
|
13 | 13 | |
|
14 | <%def name="breadcrumbs_links()"> | |
|
15 | ${_('Add new file')} @ ${h.show_id(c.commit)} ${_('Branch')}: ${c.commit.branch} | |
|
16 | </%def> | |
|
14 | <%def name="breadcrumbs_links()"></%def> | |
|
17 | 15 | |
|
18 | 16 | <%def name="menu_bar_subnav()"> |
|
19 | 17 | ${self.repo_menu(active='files')} |
|
20 | 18 | </%def> |
|
21 | 19 | |
|
22 | 20 | <%def name="main()"> |
|
21 | ||
|
23 | 22 | <div class="box"> |
|
23 | ## Template for uploads | |
|
24 | <div style="display: none" id="tpl-dropzone"> | |
|
25 | <div class="dz-preview dz-file-preview"> | |
|
26 | <div class="dz-details"> | |
|
24 | 27 | |
|
25 |
<div class=" |
|
|
26 | ${self.breadcrumbs()} | |
|
28 | <div class="dz-filename"> | |
|
29 | <span data-dz-name></span> | |
|
30 | </div> | |
|
31 | <div class="dz-filename-size"> | |
|
32 | <span class="dz-size" data-dz-size></span> | |
|
33 | ||
|
27 | 34 | </div> |
|
28 | 35 | |
|
29 | ${h.secure_form(h.route_path('repo_files_create_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path), id='eform', enctype="multipart/form-data", class_="form-horizontal", request=request)} | |
|
30 | <div class="edit-file-fieldset"> | |
|
31 | <div class="fieldset"> | |
|
32 | <div id="destination-label" class="left-label"> | |
|
33 | ${_('Path')}: | |
|
36 | <div class="dz-sending" style="display: none">${_('Uploading...')}</div> | |
|
37 | <div class="dz-response" style="display: none"> | |
|
38 | ${_('Uploaded')} 100% | |
|
39 | </div> | |
|
40 | ||
|
34 | 41 | </div> |
|
35 |
<div class=" |
|
|
36 | <div> | |
|
37 | ${h.files_breadcrumbs(c.repo_name,c.commit.raw_id,c.f_path, request.GET.get('at'))} / | |
|
38 | <input type="input-small" value="${c.f_path}" size="46" name="location" id="location"> | |
|
42 | <div class="dz-progress"> | |
|
43 | <span class="dz-upload" data-dz-uploadprogress></span> | |
|
44 | </div> | |
|
45 | ||
|
46 | <div class="dz-error-message"> | |
|
39 | 47 |
|
|
40 | 48 |
|
|
41 | 49 |
|
|
42 | 50 | |
|
43 | <div id="upload_file_container" class="fieldset"> | |
|
44 | <div class="filename-label left-label"> | |
|
45 | ${_('Filename')}: | |
|
51 | <div class="edit-file-title"> | |
|
52 | <span class="title-heading">${_('Upload new file')} @ <code>${h.show_id(c.commit)}</code></span> | |
|
53 | <span class="tag branchtag"><i class="icon-branch"></i> ${c.commit.branch}</span> | |
|
46 | 54 |
|
|
47 | <div class="right-content"> | |
|
48 | <input class="input-small" type="text" value="" size="46" name="filename_upload" id="filename_upload" placeholder="${_('No file selected')}"> | |
|
55 | ||
|
56 | <% form_url = h.route_path('repo_files_upload_file', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path) %> | |
|
57 | ##${h.secure_form(form_url, id='eform', enctype="multipart/form-data", request=request)} | |
|
58 | <div class="edit-file-fieldset"> | |
|
59 | <div class="path-items"> | |
|
60 | <ul> | |
|
61 | <li class="breadcrumb-path"> | |
|
62 | <div> | |
|
63 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path='')}"><i class="icon-home"></i></a> / | |
|
64 | <a href="${h.route_path('repo_files', repo_name=c.repo_name, commit_id=c.commit.raw_id, f_path=c.f_path)}">${c.f_path}</a> ${('/' if c.f_path else '')} | |
|
49 | 65 | </div> |
|
50 | <div class="filename-label left-label file-upload-label"> | |
|
51 | ${_('Upload file')}: | |
|
66 | </li> | |
|
67 | <li class="location-path"> | |
|
68 | ||
|
69 | </li> | |
|
70 | </ul> | |
|
71 | </div> | |
|
72 | ||
|
52 | 73 |
|
|
53 | <div class="right-content file-upload-input"> | |
|
54 | <label for="upload_file" class="btn btn-default">Browse</label> | |
|
74 | ||
|
75 | <div class="upload-form table"> | |
|
76 | <div id="files_data"> | |
|
55 | 77 | |
|
56 | <input type="file" name="upload_file" id="upload_file"> | |
|
78 | <div class="dropzone-wrapper" id="file-uploader"> | |
|
79 | <div class="dropzone-pure"> | |
|
80 | <div class="dz-message"> | |
|
81 | <i class="icon-upload" style="font-size:36px"></i></br> | |
|
82 | ${_("Drag'n Drop files here or")} <span class="link">${_('Choose your files')}</span>.<br> | |
|
83 | </div> | |
|
84 | </div> | |
|
85 | ||
|
57 | 86 | </div> |
|
58 | 87 | </div> |
|
59 | 88 | |
|
60 | 89 | </div> |
|
61 | 90 | |
|
62 | <div class="table"> | |
|
63 | <div id="files_data"> | |
|
64 | <div id="codeblock" class="codeblock"> | |
|
65 | <div class="code-header form" id="set_mode_header"> | |
|
66 | <div class="fields"> | |
|
67 | ${h.dropdownmenu('set_mode','plain',[('plain',_('plain'))],enable_filter=True)} | |
|
68 | <label for="line_wrap">${_('line wraps')}</label> | |
|
69 | ${h.dropdownmenu('line_wrap', 'off', [('on', _('on')), ('off', _('off')),])} | |
|
70 | ||
|
71 | <div id="render_preview" class="btn btn-small preview hidden" >${_('Preview')}</div> | |
|
72 | </div> | |
|
73 | </div> | |
|
74 | <div id="editor_container"> | |
|
75 | <pre id="editor_pre"></pre> | |
|
76 | <textarea id="editor" name="content" ></textarea> | |
|
77 | <div id="editor_preview"></div> | |
|
78 | </div> | |
|
79 | </div> | |
|
80 | </div> | |
|
81 | </div> | |
|
82 | ||
|
83 | <div class="edit-file-fieldset"> | |
|
91 | <div class="upload-form edit-file-fieldset"> | |
|
84 | 92 | <div class="fieldset"> |
|
85 | <div id="commit-message-label" class="commit-message-label left-label"> | |
|
86 | ${_('Commit Message')}: | |
|
87 | </div> | |
|
88 | <div class="right-content"> | |
|
89 | 93 |
|
|
90 | 94 |
|
|
91 | 95 |
|
|
92 | 96 |
|
|
93 | </div> | |
|
94 | <div class="pull-right"> | |
|
95 | ${h.reset('reset',_('Cancel'),class_="btn btn-small")} | |
|
97 | <div class="pull-left"> | |
|
96 | 98 | ${h.submit('commit_btn',_('Commit changes'),class_="btn btn-small btn-success")} |
|
97 | 99 | </div> |
|
98 | 100 | </div> |
|
99 | ${h.end_form()} | |
|
101 | ##${h.end_form()} | |
|
102 | ||
|
103 | <div class="file-upload-transaction-wrapper" style="display: none"> | |
|
104 | <div class="file-upload-transaction"> | |
|
105 | <h3>${_('Commiting...')}</h3> | |
|
106 | <p>${_('Please wait while the files are being uploaded')}</p> | |
|
107 | <p class="error" style="display: none"> | |
|
108 | ||
|
109 | </p> | |
|
110 | <i class="icon-spin animate-spin"></i> | |
|
111 | <p></p> | |
|
100 | 112 | </div> |
|
113 | </div> | |
|
114 | ||
|
115 | </div> | |
|
116 | ||
|
101 | 117 | <script type="text/javascript"> |
|
102 | 118 | |
|
103 |
$( |
|
|
119 | $(document).ready(function () { | |
|
120 | ||
|
121 | //see: https://www.dropzonejs.com/#configuration | |
|
122 | myDropzone = new Dropzone("div#file-uploader", { | |
|
123 | url: "${form_url}", | |
|
124 | headers: {"X-CSRF-Token": CSRF_TOKEN}, | |
|
125 | paramName: function () { | |
|
126 | return "files_upload" | |
|
127 | }, // The name that will be used to transfer the file | |
|
128 | parallelUploads: 20, | |
|
129 | maxFiles: 20, | |
|
130 | uploadMultiple: true, | |
|
131 | //chunking: true, // use chunking transfer, not supported at the moment | |
|
132 | //maxFilesize: 2, // in MBs | |
|
133 | autoProcessQueue: false, // if false queue will not be processed automatically. | |
|
134 | createImageThumbnails: false, | |
|
135 | previewTemplate: document.querySelector('#tpl-dropzone').innerHTML, | |
|
136 | accept: function (file, done) { | |
|
137 | done(); | |
|
138 | }, | |
|
139 | init: function () { | |
|
140 | this.on("addedfile", function (file) { | |
|
141 | ||
|
142 | }); | |
|
143 | ||
|
144 | this.on("sending", function (file, xhr, formData) { | |
|
145 | formData.append("message", $('#commit').val()); | |
|
146 | $(file.previewElement).find('.dz-sending').show(); | |
|
147 | }); | |
|
148 | ||
|
149 | this.on("success", function (file, response) { | |
|
150 | $(file.previewElement).find('.dz-sending').hide(); | |
|
151 | $(file.previewElement).find('.dz-response').show(); | |
|
152 | ||
|
153 | if (response.error !== null) { | |
|
154 | $('.file-upload-transaction-wrapper .error').html('ERROR: {0}'.format(response.error)); | |
|
155 | $('.file-upload-transaction-wrapper .error').show(); | |
|
156 | $('.file-upload-transaction-wrapper i').hide() | |
|
157 | } | |
|
158 | ||
|
159 | var redirect_url = response.redirect_url || '/'; | |
|
160 | window.location = redirect_url | |
|
161 | ||
|
162 | }); | |
|
163 | ||
|
164 | this.on("error", function (file, errorMessage, xhr) { | |
|
165 | var error = null; | |
|
166 | ||
|
167 | if (xhr !== undefined){ | |
|
168 | var httpStatus = xhr.status + " " + xhr.statusText; | |
|
169 | if (xhr.status >= 500) { | |
|
170 | error = httpStatus; | |
|
171 | } | |
|
172 | } | |
|
173 | ||
|
174 | if (error === null) { | |
|
175 | error = errorMessage.error || errorMessage || httpStatus; | |
|
176 | } | |
|
177 | ||
|
178 | $(file.previewElement).find('.dz-error-message').html('ERROR: {0}'.format(error)); | |
|
179 | }); | |
|
180 | } | |
|
181 | }); | |
|
182 | ||
|
183 | $('#commit_btn').on('click', function(e) { | |
|
184 | e.preventDefault(); | |
|
104 | 185 | var button = $(this); |
|
105 | 186 | if (button.hasClass('clicked')) { |
|
106 | 187 | button.attr('disabled', true); |
|
107 | 188 | } else { |
|
108 | 189 | button.addClass('clicked'); |
|
109 | 190 | } |
|
110 | }); | |
|
111 | 191 | |
|
112 | var hide_upload = function(){ | |
|
113 | $('#files_data').show(); | |
|
114 | $('#upload_file_container').hide(); | |
|
115 | $('#filename_container').show(); | |
|
116 | }; | |
|
117 | ||
|
118 | $('#file_enable').on('click', function(e){ | |
|
192 | var files = myDropzone.getQueuedFiles(); | |
|
193 | if (files.length === 0) { | |
|
194 | alert("Missing files"); | |
|
119 | 195 | e.preventDefault(); |
|
120 | hide_upload(); | |
|
121 | }); | |
|
122 | ||
|
123 | var renderer = ""; | |
|
124 | var reset_url = "${h.route_path('repo_files',repo_name=c.repo_name,commit_id=c.commit.raw_id,f_path=c.f_path)}"; | |
|
125 | var myCodeMirror = initCodeMirror('editor', reset_url, false); | |
|
126 | ||
|
127 | var modes_select = $('#set_mode'); | |
|
128 | fillCodeMirrorOptions(modes_select); | |
|
129 | ||
|
130 | var filename_selector = '#filename'; | |
|
131 | var callback = function(filename, mimetype, mode){ | |
|
132 | CodeMirrorPreviewEnable(mode); | |
|
133 | }; | |
|
134 | // on change of select field set mode | |
|
135 | setCodeMirrorModeFromSelect( | |
|
136 | modes_select, filename_selector, myCodeMirror, callback); | |
|
137 | ||
|
138 | // on entering the new filename set mode, from given extension | |
|
139 | setCodeMirrorModeFromInput( | |
|
140 | modes_select, filename_selector, myCodeMirror, callback); | |
|
141 | ||
|
142 | // if the file is renderable set line wraps automatically | |
|
143 | if (renderer !== ""){ | |
|
144 | var line_wrap = 'on'; | |
|
145 | $($('#line_wrap option[value="'+line_wrap+'"]')[0]).attr("selected", "selected"); | |
|
146 | setCodeMirrorLineWrap(myCodeMirror, true); | |
|
147 | 196 | } |
|
148 | 197 | |
|
149 | // on select line wraps change the editor | |
|
150 | $('#line_wrap').on('change', function(e){ | |
|
151 | var selected = e.currentTarget; | |
|
152 | var line_wraps = {'on': true, 'off': false}[selected.value]; | |
|
153 | setCodeMirrorLineWrap(myCodeMirror, line_wraps) | |
|
198 | $('.upload-form').hide(); | |
|
199 | $('.file-upload-transaction-wrapper').show(); | |
|
200 | myDropzone.processQueue(); | |
|
201 | ||
|
154 | 202 | }); |
|
155 | 203 | |
|
156 | // render preview/edit button | |
|
157 | $('#render_preview').on('click', function(e){ | |
|
158 | if($(this).hasClass('preview')){ | |
|
159 | $(this).removeClass('preview'); | |
|
160 | $(this).html("${_('Edit')}"); | |
|
161 | $('#editor_preview').show(); | |
|
162 | $(myCodeMirror.getWrapperElement()).hide(); | |
|
163 | ||
|
164 | var possible_renderer = { | |
|
165 | 'rst':'rst', | |
|
166 | 'markdown':'markdown', | |
|
167 | 'gfm': 'markdown'}[myCodeMirror.getMode().name]; | |
|
168 | var _text = myCodeMirror.getValue(); | |
|
169 | var _renderer = possible_renderer || DEFAULT_RENDERER; | |
|
170 | var post_data = {'text': _text, 'renderer': _renderer, 'csrf_token': CSRF_TOKEN}; | |
|
171 | $('#editor_preview').html(_gettext('Loading ...')); | |
|
172 | var url = pyroutes.url('repo_commit_comment_preview', | |
|
173 | {'repo_name': '${c.repo_name}', | |
|
174 | 'commit_id': '${c.commit.raw_id}'}); | |
|
175 | ||
|
176 | ajaxPOST(url, post_data, function(o){ | |
|
177 | $('#editor_preview').html(o); | |
|
178 | }) | |
|
179 | } | |
|
180 | else{ | |
|
181 | $(this).addClass('preview'); | |
|
182 | $(this).html("${_('Preview')}"); | |
|
183 | $('#editor_preview').hide(); | |
|
184 | $(myCodeMirror.getWrapperElement()).show(); | |
|
185 | } | |
|
186 | 204 | }); |
|
187 | $('#filename').focus(); | |
|
188 | 205 | |
|
189 | 206 | </script> |
|
190 | 207 | </%def> |
General Comments 0
You need to be logged in to leave comments.
Login now