mirror of
https://github.com/discourse/discourse.git
synced 2025-02-23 04:45:26 +08:00
DEV: Convert UppyImageUploader to gjs (#31310)
This commit is contained in:
parent
a585fc5a24
commit
310cd513d8
@ -1,6 +1,8 @@
|
|||||||
<UppyImageUploader
|
<UppyImageUploader
|
||||||
@imageUrl={{this.value}}
|
@imageUrl={{this.value}}
|
||||||
@placeholderUrl={{this.setting.placeholder}}
|
@placeholderUrl={{this.setting.placeholder}}
|
||||||
|
@onUploadDone={{fn (mut this.value)}}
|
||||||
|
@onUploadDeleted={{fn (mut this.value) null}}
|
||||||
@additionalParams={{hash for_site_setting=true}}
|
@additionalParams={{hash for_site_setting=true}}
|
||||||
@type="site_setting"
|
@type="site_setting"
|
||||||
@id={{concat "site-setting-image-uploader-" this.setting.setting}}
|
@id={{concat "site-setting-image-uploader-" this.setting.setting}}
|
||||||
|
@ -0,0 +1,216 @@
|
|||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import { on } from "@ember/modifier";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { guidFor } from "@ember/object/internals";
|
||||||
|
import { getOwner } from "@ember/owner";
|
||||||
|
import { service } from "@ember/service";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
import { isEmpty } from "@ember/utils";
|
||||||
|
import { modifier } from "ember-modifier";
|
||||||
|
import $ from "jquery";
|
||||||
|
import DButton from "discourse/components/d-button";
|
||||||
|
import PickFilesButton from "discourse/components/pick-files-button";
|
||||||
|
import concatClass from "discourse/helpers/concat-class";
|
||||||
|
import icon from "discourse/helpers/d-icon";
|
||||||
|
import { getURLWithCDN } from "discourse/lib/get-url";
|
||||||
|
import lightbox from "discourse/lib/lightbox";
|
||||||
|
import { authorizesOneOrMoreExtensions } from "discourse/lib/uploads";
|
||||||
|
import UppyUpload from "discourse/lib/uppy/uppy-upload";
|
||||||
|
import { i18n } from "discourse-i18n";
|
||||||
|
|
||||||
|
// Args: id, type, imageUrl, placeholderUrl, additionalParams, onUploadDone, onUploadDeleted,
|
||||||
|
export default class UppyImageUploader extends Component {
|
||||||
|
@service currentUser;
|
||||||
|
@service siteSettings;
|
||||||
|
|
||||||
|
@tracked imageFilesize;
|
||||||
|
@tracked imageFilename;
|
||||||
|
@tracked imageWidth;
|
||||||
|
@tracked imageHeight;
|
||||||
|
|
||||||
|
uppyUpload = new UppyUpload(getOwner(this), {
|
||||||
|
id: this.args.id,
|
||||||
|
type: this.args.type,
|
||||||
|
additionalParams: this.args.additionalParams,
|
||||||
|
validateUploadedFilesOptions: { imagesOnly: true },
|
||||||
|
uploadDropTargetOptions: () => ({
|
||||||
|
target: document.querySelector(
|
||||||
|
`#${this.args.id} .uploaded-image-preview`
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
uploadDone: (upload) => {
|
||||||
|
this.imageFilesize = upload.human_filesize;
|
||||||
|
this.imageFilename = upload.original_filename;
|
||||||
|
this.imageWidth = upload.width;
|
||||||
|
this.imageHeight = upload.height;
|
||||||
|
|
||||||
|
this.args.onUploadDone(upload);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
applyLightbox = modifier((element) => lightbox(element, this.siteSettings));
|
||||||
|
|
||||||
|
willDestroy() {
|
||||||
|
super.willDestroy(...arguments);
|
||||||
|
$.magnificPopup?.instance.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return (
|
||||||
|
this.notAllowed ||
|
||||||
|
this.uppyUpload?.uploading ||
|
||||||
|
this.uppyUpload?.processing
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get computedId() {
|
||||||
|
// without a fallback ID this will not be accessible
|
||||||
|
return this.args.id ? `${this.args.id}__input` : `${guidFor(this)}__input`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get disabledReason() {
|
||||||
|
if (this.disabled && this.notAllowed) {
|
||||||
|
return i18n("post.errors.no_uploads_authorized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get notAllowed() {
|
||||||
|
return !authorizesOneOrMoreExtensions(
|
||||||
|
this.currentUser?.staff,
|
||||||
|
this.siteSettings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get showingPlaceholder() {
|
||||||
|
return !this.args.imageUrl && this.args.placeholderUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
get placeholderStyle() {
|
||||||
|
if (isEmpty(this.args.placeholderUrl)) {
|
||||||
|
return htmlSafe("");
|
||||||
|
}
|
||||||
|
return htmlSafe(`background-image: url(${this.args.placeholderUrl})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get imageCdnUrl() {
|
||||||
|
if (isEmpty(this.args.imageUrl)) {
|
||||||
|
return htmlSafe("");
|
||||||
|
}
|
||||||
|
|
||||||
|
return getURLWithCDN(this.args.imageUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
get backgroundStyle() {
|
||||||
|
return htmlSafe(`background-image: url(${this.imageCdnUrl})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get imageBaseName() {
|
||||||
|
if (!isEmpty(this.args.imageUrl)) {
|
||||||
|
return this.args.imageUrl.split("/").slice(-1)[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
toggleLightbox() {
|
||||||
|
const lightboxElement = document.querySelector(
|
||||||
|
`#${this.args.id} a.lightbox`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (lightboxElement) {
|
||||||
|
$(lightboxElement).magnificPopup("open");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
handleKeyboardActivation(event) {
|
||||||
|
if (event.key === "Enter" || event.key === " ") {
|
||||||
|
event.preventDefault(); // avoid space scrolling the page
|
||||||
|
const input = document.getElementById(this.computedId);
|
||||||
|
if (input && !this.disabled) {
|
||||||
|
input.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div {{this.applyLightbox}} id={{@id}} class="image-uploader" ...attributes>
|
||||||
|
<div
|
||||||
|
class="uploaded-image-preview input-xxlarge"
|
||||||
|
style={{this.backgroundStyle}}
|
||||||
|
>
|
||||||
|
{{#if this.showingPlaceholder}}
|
||||||
|
<div
|
||||||
|
class="placeholder-overlay"
|
||||||
|
style={{this.placeholderStyle}}
|
||||||
|
></div>
|
||||||
|
{{/if}}
|
||||||
|
<div class="image-upload-controls">
|
||||||
|
<label
|
||||||
|
class="btn btn-default pad-left no-text
|
||||||
|
{{if this.disabled 'disabled'}}"
|
||||||
|
title={{this.disabledReason}}
|
||||||
|
for={{this.computedId}}
|
||||||
|
tabindex="0"
|
||||||
|
{{on "keydown" this.handleKeyboardActivation}}
|
||||||
|
>
|
||||||
|
{{icon "far-image"}}
|
||||||
|
<PickFilesButton
|
||||||
|
@registerFileInput={{this.uppyUpload.setup}}
|
||||||
|
@fileInputDisabled={{this.disabled}}
|
||||||
|
@acceptedFormatsOverride="image/*"
|
||||||
|
@fileInputId={{this.computedId}}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
{{#if @imageUrl}}
|
||||||
|
<DButton
|
||||||
|
@action={{@onUploadDeleted}}
|
||||||
|
@icon="trash-can"
|
||||||
|
class="btn-danger pad-left no-text"
|
||||||
|
/>
|
||||||
|
<DButton
|
||||||
|
@action={{this.toggleLightbox}}
|
||||||
|
@icon="discourse-expand"
|
||||||
|
@title="expand"
|
||||||
|
class="btn-default image-uploader-lightbox-btn no-text"
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<span
|
||||||
|
class={{concatClass
|
||||||
|
"btn"
|
||||||
|
(unless this.uppyUpload.uploading "hidden")
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{{i18n "upload_selector.uploading"}}
|
||||||
|
{{this.uppyUpload.uploadProgress}}%
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class={{concatClass
|
||||||
|
"btn"
|
||||||
|
(unless this.uppyUpload.processing "hidden")
|
||||||
|
}}
|
||||||
|
>{{i18n "upload_selector.processing"}}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if @imageUrl}}
|
||||||
|
<a
|
||||||
|
href={{this.imageCdnUrl}}
|
||||||
|
title={{this.imageFilename}}
|
||||||
|
rel="nofollow ugc noopener"
|
||||||
|
class="lightbox"
|
||||||
|
>
|
||||||
|
|
||||||
|
<div class="meta">
|
||||||
|
<span class="informations">
|
||||||
|
{{this.imageWidth}}x{{this.imageHeight}}
|
||||||
|
{{this.imageFilesize}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
}
|
@ -1,65 +0,0 @@
|
|||||||
<div
|
|
||||||
class="uploaded-image-preview input-xxlarge"
|
|
||||||
style={{this.backgroundStyle}}
|
|
||||||
>
|
|
||||||
{{#if this.showingPlaceholder}}
|
|
||||||
<div class="placeholder-overlay" style={{this.placeholderStyle}}></div>
|
|
||||||
{{/if}}
|
|
||||||
<div class="image-upload-controls">
|
|
||||||
<label
|
|
||||||
class="btn btn-default pad-left no-text {{if this.disabled 'disabled'}}"
|
|
||||||
title={{this.disabledReason}}
|
|
||||||
for={{this.computedId}}
|
|
||||||
tabindex="0"
|
|
||||||
{{on "keydown" this.handleKeyboardActivation}}
|
|
||||||
>
|
|
||||||
{{d-icon "far-image"}}
|
|
||||||
<PickFilesButton
|
|
||||||
@registerFileInput={{this.uppyUpload.setup}}
|
|
||||||
@fileInputDisabled={{this.disabled}}
|
|
||||||
@acceptedFormatsOverride="image/*"
|
|
||||||
@fileInputId={{this.computedId}}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{{#if this.imageUrl}}
|
|
||||||
<DButton
|
|
||||||
@action={{action "trash"}}
|
|
||||||
@icon="trash-can"
|
|
||||||
class="btn-danger pad-left no-text"
|
|
||||||
/>
|
|
||||||
<DButton
|
|
||||||
@icon="discourse-expand"
|
|
||||||
@title="expand"
|
|
||||||
@disabled={{this.loadingLightbox}}
|
|
||||||
@action={{this.toggleLightbox}}
|
|
||||||
class="btn-default image-uploader-lightbox-btn no-text"
|
|
||||||
/>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<span class="btn {{unless this.uppyUpload.uploading 'hidden'}}">{{i18n
|
|
||||||
"upload_selector.uploading"
|
|
||||||
}}
|
|
||||||
{{this.uppyUpload.uploadProgress}}%</span>
|
|
||||||
<span class="btn {{unless this.uppyUpload.processing 'hidden'}}">{{i18n
|
|
||||||
"upload_selector.processing"
|
|
||||||
}}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if this.imageUrl}}
|
|
||||||
<a
|
|
||||||
class="lightbox"
|
|
||||||
href={{this.imageCDNURL}}
|
|
||||||
title={{this.imageFilename}}
|
|
||||||
rel="nofollow ugc noopener"
|
|
||||||
>
|
|
||||||
|
|
||||||
<div class="meta">
|
|
||||||
<span class="informations">
|
|
||||||
{{this.imageWidth}}x{{this.imageHeight}}
|
|
||||||
{{this.imageFilesize}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
@ -1,157 +0,0 @@
|
|||||||
import Component from "@ember/component";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
import { or } from "@ember/object/computed";
|
|
||||||
import { guidFor } from "@ember/object/internals";
|
|
||||||
import { getOwner } from "@ember/owner";
|
|
||||||
import { next } from "@ember/runloop";
|
|
||||||
import { htmlSafe } from "@ember/template";
|
|
||||||
import { isEmpty } from "@ember/utils";
|
|
||||||
import { classNames } from "@ember-decorators/component";
|
|
||||||
import { on } from "@ember-decorators/object";
|
|
||||||
import $ from "jquery";
|
|
||||||
import discourseComputed from "discourse/lib/decorators";
|
|
||||||
import { getURLWithCDN } from "discourse/lib/get-url";
|
|
||||||
import lightbox from "discourse/lib/lightbox";
|
|
||||||
import { authorizesOneOrMoreExtensions } from "discourse/lib/uploads";
|
|
||||||
import UppyUpload from "discourse/lib/uppy/uppy-upload";
|
|
||||||
import { i18n } from "discourse-i18n";
|
|
||||||
|
|
||||||
@classNames("image-uploader")
|
|
||||||
export default class UppyImageUploader extends Component {
|
|
||||||
@or("notAllowed", "uppyUpload.uploading", "uppyUpload.processing") disabled;
|
|
||||||
|
|
||||||
uppyUpload = null;
|
|
||||||
|
|
||||||
@on("init")
|
|
||||||
setupUppyUpload() {
|
|
||||||
// The uppyUpload configuration depends on arguments. In classic components like
|
|
||||||
// this one, the arguments are not available during field initialization, so we have to
|
|
||||||
// defer until init(). When this component is glimmer-ified in future, this can be turned
|
|
||||||
// into a simple field initializer.
|
|
||||||
this.uppyUpload = new UppyUpload(getOwner(this), {
|
|
||||||
id: this.id,
|
|
||||||
type: this.type,
|
|
||||||
additionalParams: this.additionalParams,
|
|
||||||
validateUploadedFilesOptions: { imagesOnly: true },
|
|
||||||
uploadDropTargetOptions: () => ({
|
|
||||||
target: document.querySelector(`#${this.id} .uploaded-image-preview`),
|
|
||||||
}),
|
|
||||||
uploadDone: (upload) => {
|
|
||||||
this.setProperties({
|
|
||||||
imageFilesize: upload.human_filesize,
|
|
||||||
imageFilename: upload.original_filename,
|
|
||||||
imageWidth: upload.width,
|
|
||||||
imageHeight: upload.height,
|
|
||||||
});
|
|
||||||
|
|
||||||
// the value of the property used for imageUrl should be set
|
|
||||||
// in this callback. this should be done in cases where imageUrl
|
|
||||||
// is bound to a computed property of the parent component.
|
|
||||||
if (this.onUploadDone) {
|
|
||||||
this.onUploadDone(upload);
|
|
||||||
} else {
|
|
||||||
this.set("imageUrl", upload.url);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("id")
|
|
||||||
computedId(id) {
|
|
||||||
// without a fallback ID this will not be accessible
|
|
||||||
return id ? `${id}__input` : `${guidFor(this)}__input`;
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("disabled", "notAllowed")
|
|
||||||
disabledReason(disabled, notAllowed) {
|
|
||||||
if (disabled && notAllowed) {
|
|
||||||
return i18n("post.errors.no_uploads_authorized");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed(
|
|
||||||
"currentUser.staff",
|
|
||||||
"siteSettings.{authorized_extensions,authorized_extensions_for_staff}"
|
|
||||||
)
|
|
||||||
notAllowed() {
|
|
||||||
return !authorizesOneOrMoreExtensions(
|
|
||||||
this.currentUser?.staff,
|
|
||||||
this.siteSettings
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("imageUrl", "placeholderUrl")
|
|
||||||
showingPlaceholder(imageUrl, placeholderUrl) {
|
|
||||||
return !imageUrl && placeholderUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("placeholderUrl")
|
|
||||||
placeholderStyle(url) {
|
|
||||||
if (isEmpty(url)) {
|
|
||||||
return htmlSafe("");
|
|
||||||
}
|
|
||||||
return htmlSafe(`background-image: url(${url})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("imageUrl")
|
|
||||||
imageCDNURL(url) {
|
|
||||||
if (isEmpty(url)) {
|
|
||||||
return htmlSafe("");
|
|
||||||
}
|
|
||||||
|
|
||||||
return getURLWithCDN(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("imageCDNURL")
|
|
||||||
backgroundStyle(url) {
|
|
||||||
return htmlSafe(`background-image: url(${url})`);
|
|
||||||
}
|
|
||||||
|
|
||||||
@discourseComputed("imageUrl")
|
|
||||||
imageBaseName(imageUrl) {
|
|
||||||
if (isEmpty(imageUrl)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return imageUrl.split("/").slice(-1)[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@on("didRender")
|
|
||||||
_applyLightbox() {
|
|
||||||
next(() => lightbox(this.element, this.siteSettings));
|
|
||||||
}
|
|
||||||
|
|
||||||
@on("willDestroyElement")
|
|
||||||
_closeOnRemoval() {
|
|
||||||
if ($.magnificPopup?.instance) {
|
|
||||||
$.magnificPopup.instance.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
toggleLightbox() {
|
|
||||||
$(this.element.querySelector("a.lightbox"))?.magnificPopup("open");
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
trash() {
|
|
||||||
// the value of the property used for imageUrl should be cleared
|
|
||||||
// in this callback. this should be done in cases where imageUrl
|
|
||||||
// is bound to a computed property of the parent component.
|
|
||||||
if (this.onUploadDeleted) {
|
|
||||||
this.onUploadDeleted();
|
|
||||||
} else {
|
|
||||||
this.setProperties({ imageUrl: null });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
handleKeyboardActivation(event) {
|
|
||||||
if (event.key === "Enter" || event.key === " ") {
|
|
||||||
event.preventDefault(); // avoid space scrolling the page
|
|
||||||
const input = document.getElementById(this.computedId);
|
|
||||||
if (input && !this.disabled) {
|
|
||||||
input.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,4 @@
|
|||||||
import Component from "@glimmer/component";
|
import Component from "@glimmer/component";
|
||||||
import { concat } from "@ember/helper";
|
|
||||||
import { action } from "@ember/object";
|
import { action } from "@ember/object";
|
||||||
import { isBlank } from "@ember/utils";
|
import { isBlank } from "@ember/utils";
|
||||||
import UppyImageUploader from "discourse/components/uppy-image-uploader";
|
import UppyImageUploader from "discourse/components/uppy-image-uploader";
|
||||||
@ -23,7 +22,7 @@ export default class FKControlImage extends Component {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<UppyImageUploader
|
<UppyImageUploader
|
||||||
@id={{concat @field.id "-" @field.name}}
|
@id="{{@field.id}}-{{@field.name}}"
|
||||||
@imageUrl={{this.imageUrl}}
|
@imageUrl={{this.imageUrl}}
|
||||||
@onUploadDone={{this.setImage}}
|
@onUploadDone={{this.setImage}}
|
||||||
@onUploadDeleted={{this.removeImage}}
|
@onUploadDeleted={{this.removeImage}}
|
||||||
|
@ -96,6 +96,11 @@
|
|||||||
<div class="controls">
|
<div class="controls">
|
||||||
<UppyImageUploader
|
<UppyImageUploader
|
||||||
@imageUrl={{this.model.profile_background_upload_url}}
|
@imageUrl={{this.model.profile_background_upload_url}}
|
||||||
|
@onUploadDone={{fn (mut this.model.profile_background_upload_url)}}
|
||||||
|
@onUploadDeleted={{fn
|
||||||
|
(mut this.model.profile_background_upload_url)
|
||||||
|
null
|
||||||
|
}}
|
||||||
@type="profile_background"
|
@type="profile_background"
|
||||||
@id="profile-background-uploader"
|
@id="profile-background-uploader"
|
||||||
/>
|
/>
|
||||||
@ -116,6 +121,11 @@
|
|||||||
<div class="controls">
|
<div class="controls">
|
||||||
<UppyImageUploader
|
<UppyImageUploader
|
||||||
@imageUrl={{this.model.card_background_upload_url}}
|
@imageUrl={{this.model.card_background_upload_url}}
|
||||||
|
@onUploadDone={{fn (mut this.model.card_background_upload_url)}}
|
||||||
|
@onUploadDeleted={{fn
|
||||||
|
(mut this.model.card_background_upload_url)
|
||||||
|
null
|
||||||
|
}}
|
||||||
@type="card_background"
|
@type="card_background"
|
||||||
@id="profile-card-background-uploader"
|
@id="profile-card-background-uploader"
|
||||||
/>
|
/>
|
||||||
|
@ -43,9 +43,7 @@ class FieldHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get value() {
|
get value() {
|
||||||
this.context
|
this.context.dom(this.element).exists(`field '${this.name}' exists`);
|
||||||
.dom(this.element)
|
|
||||||
.exists(`Could not find element (name: ${this.name}).`);
|
|
||||||
|
|
||||||
switch (this.element.dataset.controlType) {
|
switch (this.element.dataset.controlType) {
|
||||||
case "image": {
|
case "image": {
|
||||||
|
@ -1,67 +1,70 @@
|
|||||||
import { click, render, triggerEvent } from "@ember/test-helpers";
|
import { click, render, triggerEvent } from "@ember/test-helpers";
|
||||||
import { hbs } from "ember-cli-htmlbars";
|
|
||||||
import { module, test } from "qunit";
|
import { module, test } from "qunit";
|
||||||
|
import UppyImageUploader from "discourse/components/uppy-image-uploader";
|
||||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||||
|
|
||||||
module("Integration | Component | uppy-image-uploader", function (hooks) {
|
module("Integration | Component | uppy-image-uploader", function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
|
|
||||||
test("with image", async function (assert) {
|
test("with image", async function (assert) {
|
||||||
await render(hbs`
|
await render(<template>
|
||||||
<UppyImageUploader @type="avatar" @id="uploader" @imageUrl="/images/avatar.png" @placeholderUrl="/not/used.png" />
|
<UppyImageUploader
|
||||||
`);
|
@type="avatar"
|
||||||
|
@id="uploader"
|
||||||
|
@imageUrl="/images/avatar.png"
|
||||||
|
@placeholderUrl="/not/used.png"
|
||||||
|
/>
|
||||||
|
</template>);
|
||||||
|
|
||||||
assert.dom(".d-icon-far-image").exists("displays the upload icon");
|
assert.dom(".d-icon-far-image").exists("displays the upload icon");
|
||||||
assert.dom(".d-icon-trash-can").exists("displays the trash icon");
|
assert.dom(".d-icon-trash-can").exists("displays the trash icon");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(".placeholder-overlay")
|
.dom(".placeholder-overlay")
|
||||||
.doesNotExist("it does not display the placeholder image");
|
.doesNotExist("does not display the placeholder image");
|
||||||
|
|
||||||
await click(".image-uploader-lightbox-btn");
|
await click(".image-uploader-lightbox-btn");
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.dom(".mfp-container").exists("displays the image lightbox");
|
||||||
document.querySelectorAll(".mfp-container").length,
|
|
||||||
1,
|
|
||||||
"it displays the image lightbox"
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("without image", async function (assert) {
|
test("without image", async function (assert) {
|
||||||
await render(
|
await render(<template>
|
||||||
hbs`<UppyImageUploader @type="site_setting" @id="uploader" />`
|
<UppyImageUploader @type="site_setting" @id="uploader" />
|
||||||
);
|
</template>);
|
||||||
|
|
||||||
assert.dom(".d-icon-far-image").exists("displays the upload icon");
|
assert.dom(".d-icon-far-image").exists("displays the upload icon");
|
||||||
assert.dom(".d-icon-trash-can").doesNotExist("does not display trash icon");
|
assert.dom(".d-icon-trash-can").doesNotExist("does not display trash icon");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(".image-uploader-lightbox-btn")
|
.dom(".image-uploader-lightbox-btn")
|
||||||
.doesNotExist("it does not display the button to open image lightbox");
|
.doesNotExist("does not display the button to open image lightbox");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("with placeholder", async function (assert) {
|
test("with placeholder", async function (assert) {
|
||||||
await render(
|
await render(<template>
|
||||||
hbs`<UppyImageUploader @type="composer" @id="uploader" @placeholderUrl="/images/avatar.png" />`
|
<UppyImageUploader
|
||||||
);
|
@type="composer"
|
||||||
|
@id="uploader"
|
||||||
|
@placeholderUrl="/images/avatar.png"
|
||||||
|
/>
|
||||||
|
</template>);
|
||||||
|
|
||||||
assert.dom(".d-icon-far-image").exists("displays the upload icon");
|
assert.dom(".d-icon-far-image").exists("displays the upload icon");
|
||||||
assert.dom(".d-icon-trash-can").doesNotExist("does not display trash icon");
|
assert.dom(".d-icon-trash-can").doesNotExist("does not display trash icon");
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(".image-uploader-lightbox-btn")
|
.dom(".image-uploader-lightbox-btn")
|
||||||
.doesNotExist("it does not display the button to open image lightbox");
|
.doesNotExist("does not display the button to open image lightbox");
|
||||||
|
|
||||||
assert.dom(".placeholder-overlay").exists("displays the placeholder image");
|
assert.dom(".placeholder-overlay").exists("displays the placeholder image");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("when dragging image", async function (assert) {
|
test("when dragging image", async function (assert) {
|
||||||
await render(
|
await render(<template>
|
||||||
hbs`
|
|
||||||
<UppyImageUploader @type="composer" @id="uploader1" />
|
<UppyImageUploader @type="composer" @id="uploader1" />
|
||||||
<UppyImageUploader @type="composer" @id="uploader2" />
|
<UppyImageUploader @type="composer" @id="uploader2" />
|
||||||
`
|
</template>);
|
||||||
);
|
|
||||||
|
|
||||||
const dropImage = async (target) => {
|
const dropImage = async (target) => {
|
||||||
const dataTransfer = new DataTransfer();
|
const dataTransfer = new DataTransfer();
|
Loading…
x
Reference in New Issue
Block a user