image properties converted to collapsible section container

This commit is contained in:
zadam 2021-01-30 20:21:44 +01:00
parent 1ba1f28006
commit 1c51419db5
4 changed files with 144 additions and 103 deletions

View File

@ -18,6 +18,7 @@ import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js";
import NoteListWidget from "../widgets/note_list.js"; import NoteListWidget from "../widgets/note_list.js";
import SqlResultWidget from "../widgets/sql_result.js"; import SqlResultWidget from "../widgets/sql_result.js";
import FilePropertiesWidget from "../widgets/type_property_widgets/file_properties.js"; import FilePropertiesWidget from "../widgets/type_property_widgets/file_properties.js";
import ImagePropertiesWidget from "../widgets/type_property_widgets/image_properties.js";
export default class DesktopExtraWindowLayout { export default class DesktopExtraWindowLayout {
constructor(customWidgets) { constructor(customWidgets) {
@ -50,6 +51,7 @@ export default class DesktopExtraWindowLayout {
new TabCachingWidget(() => new CollapsibleSectionContainer() new TabCachingWidget(() => new CollapsibleSectionContainer()
.child(new SearchDefinitionWidget()) .child(new SearchDefinitionWidget())
.child(new FilePropertiesWidget()) .child(new FilePropertiesWidget())
.child(new ImagePropertiesWidget())
.child(new PromotedAttributesWidget()) .child(new PromotedAttributesWidget())
.child(new OwnedAttributeListWidget()) .child(new OwnedAttributeListWidget())
.child(new InheritedAttributesWidget()) .child(new InheritedAttributesWidget())

View File

@ -29,6 +29,7 @@ import Container from "../widgets/container.js";
import SqlResultWidget from "../widgets/sql_result.js"; import SqlResultWidget from "../widgets/sql_result.js";
import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js"; import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js";
import FilePropertiesWidget from "../widgets/type_property_widgets/file_properties.js"; import FilePropertiesWidget from "../widgets/type_property_widgets/file_properties.js";
import ImagePropertiesWidget from "../widgets/type_property_widgets/image_properties.js";
const RIGHT_PANE_CSS = ` const RIGHT_PANE_CSS = `
<style> <style>
@ -158,6 +159,7 @@ export default class DesktopMainWindowLayout {
new TabCachingWidget(() => new CollapsibleSectionContainer() new TabCachingWidget(() => new CollapsibleSectionContainer()
.child(new SearchDefinitionWidget()) .child(new SearchDefinitionWidget())
.child(new FilePropertiesWidget()) .child(new FilePropertiesWidget())
.child(new ImagePropertiesWidget())
.child(new PromotedAttributesWidget()) .child(new PromotedAttributesWidget())
.child(new OwnedAttributeListWidget()) .child(new OwnedAttributeListWidget())
.child(new InheritedAttributesWidget()) .child(new InheritedAttributesWidget())

View File

@ -0,0 +1,111 @@
import server from "../../services/server.js";
import TabAwareWidget from "../tab_aware_widget.js";
import toastService from "../../services/toast.js";
import openService from "../../services/open.js";
import utils from "../../services/utils.js";
const TPL = `
<div class="image-properties">
<div style="display: flex; justify-content: space-evenly; margin: 10px;">
<span>
<strong>Original file name:</strong>
<span class="image-filename"></span>
</span>
<span>
<strong>File type:</strong>
<span class="image-filetype"></span>
</span>
<span>
<strong>File size:</strong>
<span class="image-filesize"></span>
</span>
</div>
<div class="no-print" style="display: flex; justify-content: space-evenly; margin: 10px;">
<button class="image-download btn btn-sm btn-primary" type="button">Download</button>
<button class="image-copy-to-clipboard btn btn-sm btn-primary" type="button">Copy to clipboard</button>
<button class="image-upload-new-revision btn btn-sm btn-primary" type="button">Upload new revision</button>
</div>
<input type="file" class="image-upload-new-revision-input" style="display: none">
</div>`;
export default class ImagePropertiesWidget extends TabAwareWidget {
static getType() { return "image"; }
renderTitle(note) {
return {
show: note.type === 'image',
activate: true,
$title: 'Image'
};
}
doRender() {
this.$widget = $(TPL);
this.contentSized();
this.$copyToClipboardButton = this.$widget.find(".image-copy-to-clipboard");
this.$uploadNewRevisionButton = this.$widget.find(".image-upload-new-revision");
this.$uploadNewRevisionInput = this.$widget.find(".image-upload-new-revision-input");
this.$fileName = this.$widget.find(".image-filename");
this.$fileType = this.$widget.find(".image-filetype");
this.$fileSize = this.$widget.find(".image-filesize");
this.$imageDownloadButton = this.$widget.find(".image-download");
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
this.$copyToClipboardButton.on('click', () => this.triggerEvent(`copyImageToClipboard`, {tabId: this.tabContext.tabId}));
this.$uploadNewRevisionButton.on("click", () => {
this.$uploadNewRevisionInput.trigger("click");
});
this.$uploadNewRevisionInput.on('change', async () => {
const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below
this.$uploadNewRevisionInput.val('');
const formData = new FormData();
formData.append('upload', fileToUpload);
const result = await $.ajax({
url: baseApiUrl + 'images/' + this.noteId,
headers: await server.getHeaders(),
data: formData,
type: 'PUT',
timeout: 60 * 60 * 1000,
contentType: false, // NEEDED, DON'T REMOVE THIS
processData: false, // NEEDED, DON'T REMOVE THIS
});
if (result.uploaded) {
toastService.showMessage("New image revision has been uploaded.");
await utils.clearBrowserCache();
this.refresh();
}
else {
toastService.showError("Upload of a new image revision failed: " + result.message);
}
});
}
async refreshWithNote(note) {
const attributes = note.getAttributes();
const attributeMap = utils.toObject(attributes, l => [l.name, l.value]);
this.$widget.show();
const noteComplement = await this.tabContext.getNoteComplement();
this.$fileName.text(attributeMap.originalFileName || "?");
this.$fileSize.text(noteComplement.contentLength + " bytes");
this.$fileType.text(note.mime);
const imageHash = utils.randomString(10);
}
}

View File

@ -1,12 +1,14 @@
import utils from "../../services/utils.js"; import utils from "../../services/utils.js";
import toastService from "../../services/toast.js"; import toastService from "../../services/toast.js";
import server from "../../services/server.js";
import openService from "../../services/open.js";
import TypeWidget from "./type_widget.js"; import TypeWidget from "./type_widget.js";
const TPL = ` const TPL = `
<div class="note-detail-image note-detail-printable"> <div class="note-detail-image note-detail-printable">
<style> <style>
.type-image {
height: 100%;
}
.note-detail-image { .note-detail-image {
text-align: center; text-align: center;
height: 100%; height: 100%;
@ -18,36 +20,9 @@ const TPL = `
} }
</style> </style>
<div class="no-print" style="display: flex; justify-content: space-evenly; margin: 10px;">
<button class="image-download btn btn-sm btn-primary" type="button">Download</button>
<button class="image-copy-to-clipboard btn btn-sm btn-primary" type="button">Copy to clipboard</button>
<button class="image-upload-new-revision btn btn-sm btn-primary" type="button">Upload new revision</button>
</div>
<div class="note-detail-image-wrapper"> <div class="note-detail-image-wrapper">
<img class="note-detail-image-view" /> <img class="note-detail-image-view" />
</div> </div>
<div style="display: flex; justify-content: space-evenly; margin: 10px;">
<span>
<strong>Original file name:</strong>
<span class="image-filename"></span>
</span>
<span>
<strong>File type:</strong>
<span class="image-filetype"></span>
</span>
<span>
<strong>File size:</strong>
<span class="image-filesize"></span>
</span>
</div>
<input type="file" class="image-upload-new-revision-input" style="display: none">
</div>`; </div>`;
class ImageTypeWidget extends TypeWidget { class ImageTypeWidget extends TypeWidget {
@ -58,88 +33,39 @@ class ImageTypeWidget extends TypeWidget {
this.contentSized(); this.contentSized();
this.$imageWrapper = this.$widget.find('.note-detail-image-wrapper'); this.$imageWrapper = this.$widget.find('.note-detail-image-wrapper');
this.$imageView = this.$widget.find('.note-detail-image-view'); this.$imageView = this.$widget.find('.note-detail-image-view');
this.$copyToClipboardButton = this.$widget.find(".image-copy-to-clipboard");
this.$uploadNewRevisionButton = this.$widget.find(".image-upload-new-revision");
this.$uploadNewRevisionInput = this.$widget.find(".image-upload-new-revision-input");
this.$fileName = this.$widget.find(".image-filename");
this.$fileType = this.$widget.find(".image-filetype");
this.$fileSize = this.$widget.find(".image-filesize");
this.$imageDownloadButton = this.$widget.find(".image-download");
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
this.$copyToClipboardButton.on('click',() => {
this.$imageWrapper.attr('contenteditable','true');
try {
this.selectImage(this.$imageWrapper.get(0));
const success = document.execCommand('copy');
if (success) {
toastService.showMessage("Image copied to the clipboard");
}
else {
toastService.showAndLogError("Could not copy the image to clipboard.");
}
}
finally {
window.getSelection().removeAllRanges();
this.$imageWrapper.removeAttr('contenteditable');
}
});
this.$uploadNewRevisionButton.on("click", () => {
this.$uploadNewRevisionInput.trigger("click");
});
this.$uploadNewRevisionInput.on('change', async () => {
const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below
this.$uploadNewRevisionInput.val('');
const formData = new FormData();
formData.append('upload', fileToUpload);
const result = await $.ajax({
url: baseApiUrl + 'images/' + this.noteId,
headers: await server.getHeaders(),
data: formData,
type: 'PUT',
timeout: 60 * 60 * 1000,
contentType: false, // NEEDED, DON'T REMOVE THIS
processData: false, // NEEDED, DON'T REMOVE THIS
});
if (result.uploaded) {
toastService.showMessage("New image revision has been uploaded.");
await utils.clearBrowserCache();
this.refresh();
}
else {
toastService.showError("Upload of a new image revision failed: " + result.message);
}
});
} }
async doRefresh(note) { async doRefresh(note) {
const attributes = note.getAttributes();
const attributeMap = utils.toObject(attributes, l => [l.name, l.value]);
this.$widget.show();
const noteComplement = await this.tabContext.getNoteComplement();
this.$fileName.text(attributeMap.originalFileName || "?");
this.$fileSize.text(noteComplement.contentLength + " bytes");
this.$fileType.text(note.mime);
const imageHash = utils.randomString(10); const imageHash = utils.randomString(10);
this.$imageView.prop("src", `api/images/${note.noteId}/${note.title}?${imageHash}`); this.$imageView.prop("src", `api/images/${note.noteId}/${note.title}?${imageHash}`);
} }
copyImageToClipboardEvent({tabId}) {
if (!this.isTab(tabId)) {
return;
}
this.$imageWrapper.attr('contenteditable','true');
try {
this.selectImage(this.$imageWrapper.get(0));
const success = document.execCommand('copy');
if (success) {
toastService.showMessage("Image copied to the clipboard");
}
else {
toastService.showAndLogError("Could not copy the image to clipboard.");
}
}
finally {
window.getSelection().removeAllRanges();
this.$imageWrapper.removeAttr('contenteditable');
}
}
selectImage(element) { selectImage(element) {
const selection = window.getSelection(); const selection = window.getSelection();
const range = document.createRange(); const range = document.createRange();