forked from forgejo/forgejo
Add attachment support for code review comments (#29220)
Fixes #27960, #24411, #12183 --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
parent
590f86796b
commit
f95fb8cc44
15 changed files with 227 additions and 74 deletions
|
@ -200,65 +200,68 @@ export function initGlobalCommon() {
|
|||
}
|
||||
|
||||
export function initGlobalDropzone() {
|
||||
// Dropzone
|
||||
for (const el of document.querySelectorAll('.dropzone')) {
|
||||
const $dropzone = $(el);
|
||||
const _promise = createDropzone(el, {
|
||||
url: $dropzone.data('upload-url'),
|
||||
headers: {'X-Csrf-Token': csrfToken},
|
||||
maxFiles: $dropzone.data('max-file'),
|
||||
maxFilesize: $dropzone.data('max-size'),
|
||||
acceptedFiles: (['*/*', ''].includes($dropzone.data('accepts'))) ? null : $dropzone.data('accepts'),
|
||||
addRemoveLinks: true,
|
||||
dictDefaultMessage: $dropzone.data('default-message'),
|
||||
dictInvalidFileType: $dropzone.data('invalid-input-type'),
|
||||
dictFileTooBig: $dropzone.data('file-too-big'),
|
||||
dictRemoveFile: $dropzone.data('remove-file'),
|
||||
timeout: 0,
|
||||
thumbnailMethod: 'contain',
|
||||
thumbnailWidth: 480,
|
||||
thumbnailHeight: 480,
|
||||
init() {
|
||||
this.on('success', (file, data) => {
|
||||
file.uuid = data.uuid;
|
||||
const input = $(`<input id="${data.uuid}" name="files" type="hidden">`).val(data.uuid);
|
||||
$dropzone.find('.files').append(input);
|
||||
// Create a "Copy Link" element, to conveniently copy the image
|
||||
// or file link as Markdown to the clipboard
|
||||
const copyLinkElement = document.createElement('div');
|
||||
copyLinkElement.className = 'gt-text-center';
|
||||
// The a element has a hardcoded cursor: pointer because the default is overridden by .dropzone
|
||||
copyLinkElement.innerHTML = `<a href="#" style="cursor: pointer;">${svg('octicon-copy', 14, 'copy link')} Copy link</a>`;
|
||||
copyLinkElement.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
let fileMarkdown = `[${file.name}](/attachments/${file.uuid})`;
|
||||
if (file.type.startsWith('image/')) {
|
||||
fileMarkdown = `!${fileMarkdown}`;
|
||||
} else if (file.type.startsWith('video/')) {
|
||||
fileMarkdown = `<video src="/attachments/${file.uuid}" title="${htmlEscape(file.name)}" controls></video>`;
|
||||
}
|
||||
const success = await clippie(fileMarkdown);
|
||||
showTemporaryTooltip(e.target, success ? i18n.copy_success : i18n.copy_error);
|
||||
});
|
||||
file.previewTemplate.append(copyLinkElement);
|
||||
});
|
||||
this.on('removedfile', (file) => {
|
||||
$(`#${file.uuid}`).remove();
|
||||
if ($dropzone.data('remove-url')) {
|
||||
POST($dropzone.data('remove-url'), {
|
||||
data: new URLSearchParams({file: file.uuid}),
|
||||
});
|
||||
}
|
||||
});
|
||||
this.on('error', function (file, message) {
|
||||
showErrorToast(message);
|
||||
this.removeFile(file);
|
||||
});
|
||||
},
|
||||
});
|
||||
initDropzone(el);
|
||||
}
|
||||
}
|
||||
|
||||
export function initDropzone(el) {
|
||||
const $dropzone = $(el);
|
||||
const _promise = createDropzone(el, {
|
||||
url: $dropzone.data('upload-url'),
|
||||
headers: {'X-Csrf-Token': csrfToken},
|
||||
maxFiles: $dropzone.data('max-file'),
|
||||
maxFilesize: $dropzone.data('max-size'),
|
||||
acceptedFiles: (['*/*', ''].includes($dropzone.data('accepts'))) ? null : $dropzone.data('accepts'),
|
||||
addRemoveLinks: true,
|
||||
dictDefaultMessage: $dropzone.data('default-message'),
|
||||
dictInvalidFileType: $dropzone.data('invalid-input-type'),
|
||||
dictFileTooBig: $dropzone.data('file-too-big'),
|
||||
dictRemoveFile: $dropzone.data('remove-file'),
|
||||
timeout: 0,
|
||||
thumbnailMethod: 'contain',
|
||||
thumbnailWidth: 480,
|
||||
thumbnailHeight: 480,
|
||||
init() {
|
||||
this.on('success', (file, data) => {
|
||||
file.uuid = data.uuid;
|
||||
const input = $(`<input id="${data.uuid}" name="files" type="hidden">`).val(data.uuid);
|
||||
$dropzone.find('.files').append(input);
|
||||
// Create a "Copy Link" element, to conveniently copy the image
|
||||
// or file link as Markdown to the clipboard
|
||||
const copyLinkElement = document.createElement('div');
|
||||
copyLinkElement.className = 'gt-text-center';
|
||||
// The a element has a hardcoded cursor: pointer because the default is overridden by .dropzone
|
||||
copyLinkElement.innerHTML = `<a href="#" style="cursor: pointer;">${svg('octicon-copy', 14, 'copy link')} Copy link</a>`;
|
||||
copyLinkElement.addEventListener('click', async (e) => {
|
||||
e.preventDefault();
|
||||
let fileMarkdown = `[${file.name}](/attachments/${file.uuid})`;
|
||||
if (file.type.startsWith('image/')) {
|
||||
fileMarkdown = `!${fileMarkdown}`;
|
||||
} else if (file.type.startsWith('video/')) {
|
||||
fileMarkdown = `<video src="/attachments/${file.uuid}" title="${htmlEscape(file.name)}" controls></video>`;
|
||||
}
|
||||
const success = await clippie(fileMarkdown);
|
||||
showTemporaryTooltip(e.target, success ? i18n.copy_success : i18n.copy_error);
|
||||
});
|
||||
file.previewTemplate.append(copyLinkElement);
|
||||
});
|
||||
this.on('removedfile', (file) => {
|
||||
$(`#${file.uuid}`).remove();
|
||||
if ($dropzone.data('remove-url')) {
|
||||
POST($dropzone.data('remove-url'), {
|
||||
data: new URLSearchParams({file: file.uuid}),
|
||||
});
|
||||
}
|
||||
});
|
||||
this.on('error', function (file, message) {
|
||||
showErrorToast(message);
|
||||
this.removeFile(file);
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function linkAction(e) {
|
||||
// A "link-action" can post AJAX request to its "data-url"
|
||||
// Then the browser is redirected to: the "redirect" in response, or "data-redirect" attribute, or current URL by reloading.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue