From 9999b417c2a1364ae7d05c8980a62a6342f55543 Mon Sep 17 00:00:00 2001 From: Julien Vannier Date: Fri, 9 Aug 2024 17:31:04 +0200 Subject: [PATCH 1/5] Remove sendAction from side-hover-panel & ts format --- addon/components/drag-and-drop/component.js | 4 - addon/components/layout/side-hover-panel.hbs | 5 + addon/components/layout/side-hover-panel.ts | 91 +++++++++++++++++++ .../layout/side-hover-panel/component.js | 68 -------------- .../layout/side-hover-panel/template.hbs | 2 - 5 files changed, 96 insertions(+), 74 deletions(-) create mode 100644 addon/components/layout/side-hover-panel.hbs create mode 100644 addon/components/layout/side-hover-panel.ts delete mode 100644 addon/components/layout/side-hover-panel/component.js delete mode 100644 addon/components/layout/side-hover-panel/template.hbs diff --git a/addon/components/drag-and-drop/component.js b/addon/components/drag-and-drop/component.js index fdd704d3..95875f40 100644 --- a/addon/components/drag-and-drop/component.js +++ b/addon/components/drag-and-drop/component.js @@ -17,16 +17,12 @@ export default Component.extend({ if (this._onDragElement && this.onDragClass) { return this.onDragClass; } - - return; }), dragElementInZoneClass: computed('_onDragElementInZone', 'onDragInZoneClass', function () { if (this._onDragElementInZone && this.onDragInZoneClass) { return this.onDragInZoneClass; } - - return; }), didInsertElement() { diff --git a/addon/components/layout/side-hover-panel.hbs b/addon/components/layout/side-hover-panel.hbs new file mode 100644 index 00000000..90b60a5d --- /dev/null +++ b/addon/components/layout/side-hover-panel.hbs @@ -0,0 +1,5 @@ +
+ +
{{yield}}
+
+ diff --git a/addon/components/layout/side-hover-panel.ts b/addon/components/layout/side-hover-panel.ts new file mode 100644 index 00000000..078a2a4b --- /dev/null +++ b/addon/components/layout/side-hover-panel.ts @@ -0,0 +1,91 @@ +import Component from '@glimmer/component'; +import { action } from '@ember/object'; + +interface SideHoverPanelArgs { + side: string; + stickTo: string; + width: string; + height: string; + disableScrolling: boolean; + isOverContent: boolean; + shouldAnimate: boolean; + backdropAction: () => void; +} + +export default class SideHoverPanel extends Component { + hoverPanel: HTMLElement | null = null; + panelBackdrop: HTMLElement | null = null; + + get computedClassNames(): string { + let classes = ['__side-hover-panel']; + if (this.args.isOverContent) { + classes.push('__side-hover-panel--over-content'); + } + return classes.join(' '); + } + + get backdropAction(): () => void { + return this.args.backdropAction; + } + + get side(): string { + return this.args.side ?? 'right'; + } + + get shouldAnimate(): boolean { + return this.args.shouldAnimate ?? true; + } + + get width(): string { + return this.args.width ?? '100%'; + } + + get height(): string { + return this.args.height ?? '100%'; + } + + get disableScrolling(): boolean { + return this.args.disableScrolling ?? false; + } + + get stickTo(): string { + return this.args.stickTo ?? 'right'; + } + + initialize(element: HTMLElement) { + this.hoverPanel = element.querySelector('.hover-panel')! as HTMLElement; + this.hoverPanel.classList.add(this.side + '_side'); + this.hoverPanel.classList.add(this.stickTo + '_align'); + + if (this.shouldAnimate) { + this.hoverPanel.classList.add('animate'); + } + + this.hoverPanel.classList.add(this.side + '_transform'); + + if (this.backdropAction != null) { + this.panelBackdrop = element.querySelector('.panel-backdrop'); + this.panelBackdrop!.classList.remove('hidden'); + } + + this.hoverPanel.style.width = this.width; + this.hoverPanel.style.height = this.height; + + if (this.disableScrolling) { + document.querySelector('body')?.classList.add('disable-scrolling'); + } + } + + teardown() { + this.hoverPanel?.remove(); + this.panelBackdrop?.classList.add('hidden'); + if (this.disableScrolling) { + document.querySelector('body')?.classList.remove('disable-scrolling'); + } + } + + @action + backdrop(): void { + this.args.backdropAction?.(); + } +} diff --git a/addon/components/layout/side-hover-panel/component.js b/addon/components/layout/side-hover-panel/component.js deleted file mode 100644 index dd6bb7bb..00000000 --- a/addon/components/layout/side-hover-panel/component.js +++ /dev/null @@ -1,68 +0,0 @@ -import { later } from '@ember/runloop'; -import $ from 'jquery'; -import Component from '@ember/component'; -import layout from './template'; - -export default Component.extend({ - layout, - classNames: ['__side-hover-panel'], - classNameBindings: ['isOverContent:__side-hover-panel--over-content'], - - // Those are the parameters that you can override - backdropAction: null, - side: 'right', - shouldAnimate: true, - width: '100%', - height: '100%', - disableScrolling: false, - stickTo: 'right', - - didInsertElement() { - this._super(...arguments); - let hoverPanel = this.$('.hover-panel'); - hoverPanel.addClass(this.side + '_side'); - hoverPanel.addClass(this.stickTo + '_align'); - - // Set animationsaddClass - if (this.shouldAnimate === true) { - hoverPanel.addClass('animate'); - } - - // Insert panel - later(() => { - hoverPanel.addClass(this.side + '_transform'); - }); - - // Insert backdrop - if (this.backdropAction != null) { - this.$('.panel-backdrop').removeClass('hidden'); - } - - // Set panel dimensions - hoverPanel.css({ - width: this.width, - height: this.height - }); - - // Disable scrolling - if (this.disableScrolling === true) { - $('body').addClass('disable-scrolling'); - } - }, - - willDestroyElement() { - this._super(...arguments); - // Re-enable scrolling - this.$('.hover-panel').remove(); - this.$('.panel-backdrop').addClass('hidden'); - if (this.disableScrolling === true) { - $('body').removeClass('disable-scrolling'); - } - }, - - actions: { - sendBackdropAction() { - this.sendAction('backdropAction'); - } - } -}); diff --git a/addon/components/layout/side-hover-panel/template.hbs b/addon/components/layout/side-hover-panel/template.hbs deleted file mode 100644 index 22471a26..00000000 --- a/addon/components/layout/side-hover-panel/template.hbs +++ /dev/null @@ -1,2 +0,0 @@ - -
{{yield}}
From 8a4ef5dd1164336fa2b4a72d72b6f52361229656 Mon Sep 17 00:00:00 2001 From: Julien Vannier Date: Tue, 1 Oct 2024 18:25:15 +0200 Subject: [PATCH 2/5] Update u-edit file-uploader to use OSS::Upload area component --- addon/components/drag-and-drop/component.js | 4 ++ addon/components/layout/side-hover-panel.hbs | 2 +- addon/components/layout/side-hover-panel.ts | 14 ++--- .../shared-triggers/modals/file-uploader.hbs | 60 ++++--------------- .../shared-triggers/modals/file-uploader.js | 40 ------------- .../shared-triggers/modals/file-uploader.ts | 41 +++++++++++++ .../{image-upload.js => image-upload.ts} | 8 ++- .../shared-triggers/modals/pdf-upload.js | 6 -- .../shared-triggers/modals/pdf-upload.ts | 12 ++++ translations/en-us.yaml | 26 ++------ 10 files changed, 90 insertions(+), 123 deletions(-) delete mode 100644 addon/components/u-edit/shared-triggers/modals/file-uploader.js create mode 100644 addon/components/u-edit/shared-triggers/modals/file-uploader.ts rename addon/components/u-edit/shared-triggers/modals/{image-upload.js => image-upload.ts} (51%) delete mode 100644 addon/components/u-edit/shared-triggers/modals/pdf-upload.js create mode 100644 addon/components/u-edit/shared-triggers/modals/pdf-upload.ts diff --git a/addon/components/drag-and-drop/component.js b/addon/components/drag-and-drop/component.js index 95875f40..fdd704d3 100644 --- a/addon/components/drag-and-drop/component.js +++ b/addon/components/drag-and-drop/component.js @@ -17,12 +17,16 @@ export default Component.extend({ if (this._onDragElement && this.onDragClass) { return this.onDragClass; } + + return; }), dragElementInZoneClass: computed('_onDragElementInZone', 'onDragInZoneClass', function () { if (this._onDragElementInZone && this.onDragInZoneClass) { return this.onDragInZoneClass; } + + return; }), didInsertElement() { diff --git a/addon/components/layout/side-hover-panel.hbs b/addon/components/layout/side-hover-panel.hbs index 90b60a5d..db6c4beb 100644 --- a/addon/components/layout/side-hover-panel.hbs +++ b/addon/components/layout/side-hover-panel.hbs @@ -1,5 +1,5 @@
- +
{{yield}}
diff --git a/addon/components/layout/side-hover-panel.ts b/addon/components/layout/side-hover-panel.ts index 078a2a4b..5a50738a 100644 --- a/addon/components/layout/side-hover-panel.ts +++ b/addon/components/layout/side-hover-panel.ts @@ -9,7 +9,7 @@ interface SideHoverPanelArgs { disableScrolling: boolean; isOverContent: boolean; shouldAnimate: boolean; - backdropAction: () => void; + backdropAction?(): void; } export default class SideHoverPanel extends Component { @@ -24,10 +24,6 @@ export default class SideHoverPanel extends Component { return classes.join(' '); } - get backdropAction(): () => void { - return this.args.backdropAction; - } - get side(): string { return this.args.side ?? 'right'; } @@ -52,7 +48,8 @@ export default class SideHoverPanel extends Component { return this.args.stickTo ?? 'right'; } - initialize(element: HTMLElement) { + @action + initialize(element: HTMLElement): void { this.hoverPanel = element.querySelector('.hover-panel')! as HTMLElement; this.hoverPanel.classList.add(this.side + '_side'); this.hoverPanel.classList.add(this.stickTo + '_align'); @@ -63,7 +60,7 @@ export default class SideHoverPanel extends Component { this.hoverPanel.classList.add(this.side + '_transform'); - if (this.backdropAction != null) { + if (this.args.backdropAction) { this.panelBackdrop = element.querySelector('.panel-backdrop'); this.panelBackdrop!.classList.remove('hidden'); } @@ -76,7 +73,8 @@ export default class SideHoverPanel extends Component { } } - teardown() { + @action + teardown(): void { this.hoverPanel?.remove(); this.panelBackdrop?.classList.add('hidden'); if (this.disableScrolling) { diff --git a/addon/components/u-edit/shared-triggers/modals/file-uploader.hbs b/addon/components/u-edit/shared-triggers/modals/file-uploader.hbs index d74df7d4..a55792ee 100644 --- a/addon/components/u-edit/shared-triggers/modals/file-uploader.hbs +++ b/addon/components/u-edit/shared-triggers/modals/file-uploader.hbs @@ -7,61 +7,27 @@ {{/if}}
- +
- {{#drag-and-drop - class="drop-zone upf-align--center" onDragClass="drop-zone-active" onDropFiles=this.onDropFiles}} - {{t - -
- - {{#if this.processing}} -

{{t (concat "uedit_editor.toolbar." this.titleKey ".processing") filename=this.file.name}}

- {{/if}} - -
-

{{t (concat "uedit_editor.toolbar." this.titleKey ".drop_file")}}

- -

- {{t (concat "uedit_editor.toolbar." this.titleKey ".or")}}
- - {{file-uploader - file=this.droppedFile allowedExtensions=this.allowedExtensions headers=this.uploaderHeaders - extra=this.uploaderExtra maxSize="10 MB" text=(t (concat "uedit_editor.toolbar." this.titleKey ".browse")) - beforeUpload=this.beforeUpload didError=this.onError didUpload=this.didUpload}} -

-
- {{/drag-and-drop}} - - {{#if (and this.file.name (not this.processing))}} -
- - -
-
- - -
- {{this.file.name}} -
-
- -
- -
-
-
- {{/if}} + - <:footer>
- + { + @service declare uploader: UploaderInterface; + + privacy: string = 'public'; + scope: string = 'anonymous'; + + @tracked directURL: string | null = null; + @tracked fileURL: string | null = null; + + @action + onSuccessfulFileUpload(artifact: FileArtifact): void { + this.fileURL = artifact.url; + } + + @action + onFileDeletion(): void { + this.fileURL = null; + } + + @action + addFile(): void { + if (this.directURL) { + this.args.insertFile(this.directURL); + } else if (this.fileURL) { + this.args.insertFile(this.fileURL); + } + this.directURL = this.fileURL = null; + } +} diff --git a/addon/components/u-edit/shared-triggers/modals/image-upload.js b/addon/components/u-edit/shared-triggers/modals/image-upload.ts similarity index 51% rename from addon/components/u-edit/shared-triggers/modals/image-upload.js rename to addon/components/u-edit/shared-triggers/modals/image-upload.ts index b82d724a..78de6c6a 100644 --- a/addon/components/u-edit/shared-triggers/modals/image-upload.js +++ b/addon/components/u-edit/shared-triggers/modals/image-upload.ts @@ -1,6 +1,12 @@ import UEDitFileUploader from '@upfluence/ember-upf-utils/components/u-edit/shared-triggers/modals/file-uploader'; +import { FileValidator } from '@upfluence/oss-components/addon/types/uploader'; export default class UEditImageUploadComponent extends UEDitFileUploader { - allowedExtensions = ['jpg', 'jpeg', 'png', 'gif'].join(','); titleKey = 'image'; + fileUploadRules: FileValidator[] = [ + { + type: 'filetype', + value: ['jpg', 'jpeg', 'png', 'gif'] + } + ]; } diff --git a/addon/components/u-edit/shared-triggers/modals/pdf-upload.js b/addon/components/u-edit/shared-triggers/modals/pdf-upload.js deleted file mode 100644 index 8e1b2455..00000000 --- a/addon/components/u-edit/shared-triggers/modals/pdf-upload.js +++ /dev/null @@ -1,6 +0,0 @@ -import UEDitFileUploader from '@upfluence/ember-upf-utils/components/u-edit/shared-triggers/modals/file-uploader'; - -export default class UEditPDFUploadComponent extends UEDitFileUploader { - allowedExtensions = 'pdf'; - titleKey = 'pdf'; -} diff --git a/addon/components/u-edit/shared-triggers/modals/pdf-upload.ts b/addon/components/u-edit/shared-triggers/modals/pdf-upload.ts new file mode 100644 index 00000000..7ae666be --- /dev/null +++ b/addon/components/u-edit/shared-triggers/modals/pdf-upload.ts @@ -0,0 +1,12 @@ +import UEDitFileUploader from '@upfluence/ember-upf-utils/components/u-edit/shared-triggers/modals/file-uploader'; +import { FileValidator } from '@upfluence/oss-components/types/uploader'; + +export default class UEditPDFUploadComponent extends UEDitFileUploader { + titleKey: string = 'pdf'; + fileUploadRules: FileValidator[] = [ + { + type: 'filetype', + value: ['pdf'] + } + ]; +} diff --git a/translations/en-us.yaml b/translations/en-us.yaml index ec724434..aadc30e2 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -57,30 +57,16 @@ file_uploader: upload: Upload uedit_editor: toolbar: + cancel: Cancel + by_url: 'By URL:' image: title: Add Image - by_url: - label: 'By URL:' - placeholder: https://example.org/image.png - processing: 'Processing {filename}...' - processed_file: - title: Uploaded Files - drop_file: Drop your file here - or: or - browse: Browse - cancel: Cancel + subtitle: File must be in jpg, jpeg, png, or gif format + placeholder: https://example.org/image.png pdf: title: Add PDF - by_url: - label: 'By URL:' - placeholder: https://example.org/file.pdf - processing: 'Processing {filename}...' - processed_file: - title: Uploaded Files - drop_file: Drop your file here - or: or - browse: Browse - cancel: Cancel + subtitle: File must be in pdf format + placeholder: https://example.org/file.pdf alert: title: PDF display optimization subtitle: Some mobile browsers may have trouble displaying PDFs correctly. For a better experience, we recommend using the native PDF upload feature. From ca113fd9018b39a94cf53f4058609f6ea3876a49 Mon Sep 17 00:00:00 2001 From: Julien Vannier Date: Tue, 1 Oct 2024 18:44:25 +0200 Subject: [PATCH 3/5] Remove old drag-and-drop component --- addon/components/drag-and-drop/component.js | 100 ------------------ addon/components/drag-and-drop/template.hbs | 5 - .../shared-triggers/modals/file-uploader.ts | 1 + app/components/drag-and-drop/component.js | 1 - app/styles/components/drag-and-drop.less | 21 +--- 5 files changed, 6 insertions(+), 122 deletions(-) delete mode 100644 addon/components/drag-and-drop/component.js delete mode 100644 addon/components/drag-and-drop/template.hbs delete mode 100644 app/components/drag-and-drop/component.js diff --git a/addon/components/drag-and-drop/component.js b/addon/components/drag-and-drop/component.js deleted file mode 100644 index fdd704d3..00000000 --- a/addon/components/drag-and-drop/component.js +++ /dev/null @@ -1,100 +0,0 @@ -import Component from '@ember/component'; - -import { computed } from '@ember/object'; -import $ from 'jquery'; -import layout from './template'; - -export default Component.extend({ - layout, - classNames: ['__drag-and-drop'], - classNameBindings: ['dragElementClass', 'dragElementInZoneClass'], - - _onDragElement: false, - _onDragElementInZone: false, - _nodeCollection: $(), - - dragElementClass: computed('_onDragElement', 'onDragClass', function () { - if (this._onDragElement && this.onDragClass) { - return this.onDragClass; - } - - return; - }), - - dragElementInZoneClass: computed('_onDragElementInZone', 'onDragInZoneClass', function () { - if (this._onDragElementInZone && this.onDragInZoneClass) { - return this.onDragInZoneClass; - } - - return; - }), - - didInsertElement() { - this._super(); - this._nodeCollection = this.$(); - this.$() - .on('dragover', false) - .on('dragenter', this._documentDragEnter.bind(this)) - .on('dragleave', this._documentDragLeave.bind(this)) - .on('drop', this._documentDrop.bind(this)); - }, - - dragEnter() { - if (this._onDragElementInZone) { - return; - } - - this.set('_onDragElementInZone', true); - this.sendAction('onEnterDropZone'); - }, - - dragLeave() { - if (!this._onDragElementInZone) { - return; - } - - this.set('_onDragElementInZone', false); - this.sendAction('onLeaveDropZone'); - }, - - dragOver(event) { - event.preventDefault(); - }, - - drop(event) { - event.preventDefault(); - this.set('_onDragElementInZone', false); - this.sendAction('onDropFiles', event.dataTransfer.files); - }, - - _documentDragEnter(event) { - if (!this._nodeCollection.length) { - this.set('_onDragElement', true); - this.sendAction('onEnter'); - } - - this._nodeCollection = this._nodeCollection.add(event.target); - }, - - _documentDragLeave(event) { - this._nodeCollection = this._nodeCollection.not(event.target); - if (!this._nodeCollection.length) { - this.set('_onDragElement', false); - this.sendAction('onLeave'); - } - }, - - _documentDrop() { - this._nodeCollection = $(); - this.set('_onDragElement', false); - }, - - willDestroyElement() { - this._super(...arguments); - this.$() - .off('dragover', false) - .off('dragenter', this._documentDragEnter.bind(this)) - .off('dragleave', this._documentDragLeave.bind(this)) - .off('drop', this._documentDrop.bind(this)); - } -}); diff --git a/addon/components/drag-and-drop/template.hbs b/addon/components/drag-and-drop/template.hbs deleted file mode 100644 index 5088e421..00000000 --- a/addon/components/drag-and-drop/template.hbs +++ /dev/null @@ -1,5 +0,0 @@ -{{#if _onDragElement}} -
-{{/if}} - -{{yield}} diff --git a/addon/components/u-edit/shared-triggers/modals/file-uploader.ts b/addon/components/u-edit/shared-triggers/modals/file-uploader.ts index f28d35c2..41fa03ef 100644 --- a/addon/components/u-edit/shared-triggers/modals/file-uploader.ts +++ b/addon/components/u-edit/shared-triggers/modals/file-uploader.ts @@ -8,6 +8,7 @@ import { FileArtifact } from '@upfluence/oss-components/types/uploader'; interface UEditFileUploaderSignature { insertFile(fileURL: string): void; + closeAction(): void; } export default class UEditFileUploader extends Component { diff --git a/app/components/drag-and-drop/component.js b/app/components/drag-and-drop/component.js deleted file mode 100644 index bc4fea6f..00000000 --- a/app/components/drag-and-drop/component.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from '@upfluence/ember-upf-utils/components/drag-and-drop/component'; diff --git a/app/styles/components/drag-and-drop.less b/app/styles/components/drag-and-drop.less index 2a99b67d..29e58f6c 100644 --- a/app/styles/components/drag-and-drop.less +++ b/app/styles/components/drag-and-drop.less @@ -1,31 +1,20 @@ -.__drag-and-drop { - position: relative; -} - -.__drag-and-drop-overlay { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - z-index: 1000; -} - .uedit .uedit__loading-image-upload { position: absolute; bottom: 0; right: 0; - margin: @spacing-xxx-sm; + margin: var(--spacing-px-6); &--hidden { visibility: hidden; } .spinner { - margin: 0 0 0 @spacing-xxx-sm; + margin: 0 0 0 var(--spacing-px-6); width: auto; - .bounce1, .bounce2, .bounce3 { + .bounce1, + .bounce2, + .bounce3 { margin-left: 1px; width: 8px; height: 8px; From 6d52e41fb549123cc791002306d7541a168004cc Mon Sep 17 00:00:00 2001 From: Julien Vannier Date: Wed, 2 Oct 2024 11:55:32 +0200 Subject: [PATCH 4/5] Add tests --- .../shared-triggers/modals/file-uploader.ts | 5 +- .../modals/image-upload-test.js | 47 ------- .../modals/image-upload-test.ts | 121 +++++++++++++++++ .../shared-triggers/modals/pdf-upload-test.js | 47 ------- .../shared-triggers/modals/pdf-upload-test.ts | 122 ++++++++++++++++++ .../components/utils/address-form-test.ts | 4 +- .../components/utils/utm-link-builder-test.ts | 8 +- translations/en-us.yaml | 2 +- 8 files changed, 252 insertions(+), 104 deletions(-) delete mode 100644 tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.js create mode 100644 tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.ts delete mode 100644 tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.js create mode 100644 tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.ts diff --git a/addon/components/u-edit/shared-triggers/modals/file-uploader.ts b/addon/components/u-edit/shared-triggers/modals/file-uploader.ts index 41fa03ef..78980f7d 100644 --- a/addon/components/u-edit/shared-triggers/modals/file-uploader.ts +++ b/addon/components/u-edit/shared-triggers/modals/file-uploader.ts @@ -3,8 +3,7 @@ import { tracked } from '@glimmer/tracking'; import { action } from '@ember/object'; import { inject as service } from '@ember/service'; -import UploaderInterface from '@upfluence/oss-components/types/uploader'; -import { FileArtifact } from '@upfluence/oss-components/types/uploader'; +import UploaderInterface, { FileArtifact, FilePrivacy } from '@upfluence/oss-components/types/uploader'; interface UEditFileUploaderSignature { insertFile(fileURL: string): void; @@ -14,7 +13,7 @@ interface UEditFileUploaderSignature { export default class UEditFileUploader extends Component { @service declare uploader: UploaderInterface; - privacy: string = 'public'; + privacy: string = FilePrivacy.PUBLIC; scope: string = 'anonymous'; @tracked directURL: string | null = null; diff --git a/tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.js b/tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.js deleted file mode 100644 index 69dab750..00000000 --- a/tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.js +++ /dev/null @@ -1,47 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { setupIntl } from 'ember-intl/test-support'; -import Service from '@ember/service'; -import { click, fillIn, render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; -import sinon from 'sinon'; - -class SessionServiceStub extends Service {} - -module('Integration | Component | u-edit/shared-triggers/modals/image-upload', function (hooks) { - setupRenderingTest(hooks); - setupIntl(hooks); - - hooks.beforeEach(function () { - this.owner.register('service:session', SessionServiceStub); - this.onClose = sinon.stub(); - }); - - test('can not insert image if there is no url set', async function (assert) { - this.insertImage = () => {}; - - await render( - hbs`` - ); - - assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').hasAttribute('disabled'); - }); - - test('an image is correctly added via its url in the editor', async function (assert) { - assert.expect(2); - - this.displayImageUpload = true; - this.insertImage = (url) => { - assert.equal(url, 'https://via.placeholder.com/350x150'); - }; - - await render( - hbs`` - ); - await fillIn('.uedit-file-uploader input.upf-input', 'https://via.placeholder.com/350x150'); - - assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').hasNoAttribute('disabled'); - - await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); - }); -}); diff --git a/tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.ts b/tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.ts new file mode 100644 index 00000000..fdf0a957 --- /dev/null +++ b/tests/integration/components/u-edit/shared-triggers/modals/image-upload-test.ts @@ -0,0 +1,121 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { setupIntl } from 'ember-intl/test-support'; +import { click, typeIn, render, triggerEvent, waitFor } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; +import sinon from 'sinon'; + +import MockUploader from '@upfluence/oss-components/test-support/services/uploader'; + +const FILE: File = new File( + [new Blob(['iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='])], + '1px.png', + { type: 'image/png' } +); +const URL: string = 'https://www.test.com/350x150.png'; + +module('Integration | Component | u-edit/shared-triggers/modals/image-upload', function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks); + + hooks.beforeEach(function () { + this.owner.register('service:uploader', MockUploader); + this.onClose = sinon.stub(); + this.insertImage = sinon.stub(); + }); + + test('it renders', async function (assert) { + await render( + hbs`` + ); + assert.dom('.uedit-file-uploader').exists(); + }); + + test('the modal title is correct', async function (assert) { + await render( + hbs`` + ); + assert.dom('header .title').hasText('Add image'); + }); + + test('it calls the @onClose', async function (assert) { + await render( + hbs`` + ); + await click('[data-control-name="close-modal-button"]'); + assert.true(this.onClose.calledOnceWithExactly()); + }); + + test("the alert info isn't rendered", async function (assert) { + await render( + hbs`` + ); + assert.dom('.upf-alert.upf-alert--info').doesNotExist(); + }); + + module('for the url input', () => { + test('the placeholder is correct', async function (assert) { + await render( + hbs`` + ); + assert.dom('.upf-input').hasAttribute('placeholder', 'https://example.org/image.png'); + }); + + test('the primary action is disabled when input is empty', async function (assert) { + await render( + hbs`` + ); + assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').isDisabled(); + }); + + test('the @insertImage method is called with correct args', async function (assert) { + await render( + hbs`` + ); + + await typeIn('.uedit-file-uploader input.upf-input', URL, { delay: 0 }); + await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); + assert.true(this.insertImage.calledOnceWithExactly(URL)); + }); + }); + + module('for the uploader', () => { + test('the primary action is disabled', async function (assert) { + await render( + hbs`` + ); + assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').isDisabled(); + }); + + test('the @insertImage method is called with correct args', async function (assert) { + await render( + hbs`` + ); + await triggerEvent('.oss-upload-area', 'drop', { + dataTransfer: { + files: [FILE] + } + }); + await waitFor('[data-control-name="upload-item-edit-button"]'); + await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); + + assert.true(this.insertImage.calledOnceWithExactly('https://oss-components.upfluence.co/uploader/foo.png')); + }); + }); + + test('the input URL has priority over uploader', async function (assert) { + await render( + hbs`` + ); + await typeIn('.uedit-file-uploader input.upf-input', URL, { delay: 0 }); + + await triggerEvent('.oss-upload-area', 'drop', { + dataTransfer: { + files: [FILE] + } + }); + await waitFor('[data-control-name="upload-item-edit-button"]'); + await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); + assert.true(this.insertImage.calledOnceWithExactly(URL)); + }); +}); diff --git a/tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.js b/tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.js deleted file mode 100644 index 1b090411..00000000 --- a/tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.js +++ /dev/null @@ -1,47 +0,0 @@ -import { module, test } from 'qunit'; -import { setupRenderingTest } from 'ember-qunit'; -import { setupIntl } from 'ember-intl/test-support'; -import Service from '@ember/service'; -import { click, fillIn, render } from '@ember/test-helpers'; -import { hbs } from 'ember-cli-htmlbars'; -import sinon from 'sinon'; - -class SessionServiceStub extends Service {} - -module('Integration | Component | u-edit/shared-triggers/modals/pdf-upload', function (hooks) { - setupRenderingTest(hooks); - setupIntl(hooks); - - hooks.beforeEach(function () { - this.owner.register('service:session', SessionServiceStub); - this.onClose = sinon.stub(); - }); - - test('can not insert pdf if there is no url set', async function (assert) { - this.insertPDF = () => {}; - - await render( - hbs`` - ); - - assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').hasAttribute('disabled'); - }); - - test('an image is correctly added via its url in the editor', async function (assert) { - assert.expect(2); - - this.displayImageUpload = true; - this.insertPDF = (url) => { - assert.equal(url, 'http://www.africau.edu/images/default/sample.pdf'); - }; - - await render( - hbs`` - ); - await fillIn('.uedit-file-uploader input.upf-input', 'http://www.africau.edu/images/default/sample.pdf'); - - assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').hasNoAttribute('disabled'); - - await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); - }); -}); diff --git a/tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.ts b/tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.ts new file mode 100644 index 00000000..cb4cc1dc --- /dev/null +++ b/tests/integration/components/u-edit/shared-triggers/modals/pdf-upload-test.ts @@ -0,0 +1,122 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { setupIntl } from 'ember-intl/test-support'; +import { click, fillIn, render, triggerEvent, typeIn, waitFor } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; +import sinon from 'sinon'; + +import MockUploader from '@upfluence/oss-components/test-support/services/uploader'; + +const FILE: File = new File( + [new Blob(['iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=='])], + '1px.pdf', + { type: 'application/pdf' } +); +const URL: string = 'https://www.test.com/sample.pdf'; + +module('Integration | Component | u-edit/shared-triggers/modals/pdf-upload', function (hooks) { + setupRenderingTest(hooks); + setupIntl(hooks); + + hooks.beforeEach(function () { + this.owner.register('service:uploader', MockUploader); + this.onClose = sinon.stub(); + this.insertImage = sinon.stub(); + }); + + test('it renders', async function (assert) { + await render( + hbs`` + ); + assert.dom('.uedit-file-uploader').exists(); + }); + + test('the modal title is correct', async function (assert) { + await render( + hbs`` + ); + assert.dom('header .title').hasText('Add PDF'); + }); + + test('it calls the @onClose', async function (assert) { + await render( + hbs`` + ); + await click('[data-control-name="close-modal-button"]'); + assert.true(this.onClose.calledOnceWithExactly()); + }); + + test('the alert info is rendered', async function (assert) { + await render( + hbs`` + ); + assert.dom('.upf-alert.upf-alert--info').exists(); + }); + + module('for the url input', () => { + test('the placeholder is correct', async function (assert) { + await render( + hbs`` + ); + assert.dom('.upf-input').hasAttribute('placeholder', 'https://example.org/file.pdf'); + }); + + test('the primary action is disabled when input is empty', async function (assert) { + await render( + hbs`` + ); + assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').isDisabled(); + }); + + test('the @insertImage method is called with correct args', async function (assert) { + await render( + hbs`` + ); + + await fillIn('.uedit-file-uploader input.upf-input', URL); + await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); + assert.true(this.insertImage.calledOnceWithExactly(URL)); + }); + }); + + module('for the uploader', () => { + test('the primary action is disabled', async function (assert) { + await render( + hbs`` + ); + assert.dom('.uedit-file-uploader button.upf-btn.upf-btn--primary').isDisabled(); + }); + + test('the @insertImage method is called with correct args', async function (assert) { + await render( + hbs`` + ); + await triggerEvent('.oss-upload-area', 'drop', { + dataTransfer: { + files: [FILE] + } + }); + await waitFor('[data-control-name="upload-item-edit-button"]'); + + await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); + + assert.true(this.insertImage.calledOnceWithExactly('https://oss-components.upfluence.co/uploader/foo.png')); + }); + }); + + test('the input URL has priority over uploader', async function (assert) { + await render( + hbs`` + ); + await typeIn('.uedit-file-uploader input.upf-input', URL, { delay: 0 }); + + await triggerEvent('.oss-upload-area', 'drop', { + dataTransfer: { + files: [FILE] + } + }); + await waitFor('[data-control-name="upload-item-edit-button"]'); + await click('.uedit-file-uploader button.upf-btn.upf-btn--primary'); + assert.true(this.insertImage.calledOnceWithExactly(URL)); + }); +}); diff --git a/tests/integration/components/utils/address-form-test.ts b/tests/integration/components/utils/address-form-test.ts index a4a88bf7..eab76990 100644 --- a/tests/integration/components/utils/address-form-test.ts +++ b/tests/integration/components/utils/address-form-test.ts @@ -40,7 +40,7 @@ module('Integration | Component | utils/address-form', function (hooks) { hbs`` ); - await typeIn('[data-control-name="address-form-city"] input', 'f'); + await typeIn('[data-control-name="address-form-city"] input', 'f', { delay: 0 }); await click('[data-control-name="address-form-state"] .upf-input'); await click('[data-control-name="address-form-state"] .upf-infinite-select__item:nth-child(1)'); assert.ok(this.onChange.calledWith(this.address, true)); @@ -76,7 +76,7 @@ module('Integration | Component | utils/address-form', function (hooks) { hbs`` ); - await typeIn('[data-control-name="address-form-phone"] input', '+8'); + await typeIn('[data-control-name="address-form-phone"] input', '+8', { delay: 0 }); assert.ok(this.onChange.calledWith(this.address, false)); }); }); diff --git a/tests/integration/components/utils/utm-link-builder-test.ts b/tests/integration/components/utils/utm-link-builder-test.ts index 32170396..1bb66fbe 100644 --- a/tests/integration/components/utils/utm-link-builder-test.ts +++ b/tests/integration/components/utils/utm-link-builder-test.ts @@ -52,7 +52,7 @@ module('Integration | Component | utils/utm-link-builder', function (hooks) { ); utmFields.utm_source = 'a'; - await typeIn('[data-control-name="utm_source_input"] .upf-input', 'a'); + await typeIn('[data-control-name="utm_source_input"] .upf-input', 'a', { delay: 0 }); assert.true( this.onChange.calledWith( '{link_url}?utm_source=a&utm_medium={medium_field}&utm_campaign={campaign_field}', @@ -63,7 +63,7 @@ module('Integration | Component | utils/utm-link-builder', function (hooks) { ); utmFields.utm_medium = 'b'; - await typeIn('[data-control-name="utm_medium_input"] .upf-input', 'b'); + await typeIn('[data-control-name="utm_medium_input"] .upf-input', 'b', { delay: 0 }); assert.true( this.onChange.calledWith( '{link_url}?utm_source=a&utm_medium=b&utm_campaign={campaign_field}', @@ -74,7 +74,7 @@ module('Integration | Component | utils/utm-link-builder', function (hooks) { ); utmFields.utm_campaign = 'c'; - await typeIn('[data-control-name="utm_campaign_input"] .upf-input', 'c'); + await typeIn('[data-control-name="utm_campaign_input"] .upf-input', 'c', { delay: 0 }); assert.true(this.onChange.calledWith('{link_url}?utm_source=a&utm_medium=b&utm_campaign=c', true, true, utmFields)); await settled(); }); @@ -82,7 +82,7 @@ module('Integration | Component | utils/utm-link-builder', function (hooks) { test('If a space character is inputed, it is replaced with a + sign', async function (assert) { await render(hbs``); await click('.upf-toggle'); - await typeIn('[data-control-name="utm_source_input"] .upf-input', 'a a'); + await typeIn('[data-control-name="utm_source_input"] .upf-input', 'a a', { delay: 0 }); await settled(); assert.dom('[data-control-name="utm_source_input"] .upf-input').hasValue('a+a'); }); diff --git a/translations/en-us.yaml b/translations/en-us.yaml index aadc30e2..c440b47c 100644 --- a/translations/en-us.yaml +++ b/translations/en-us.yaml @@ -60,7 +60,7 @@ uedit_editor: cancel: Cancel by_url: 'By URL:' image: - title: Add Image + title: Add image subtitle: File must be in jpg, jpeg, png, or gif format placeholder: https://example.org/image.png pdf: From 74573ee2eb28ed36fd5bd83fd424b183b8085982 Mon Sep 17 00:00:00 2001 From: Julien Vannier Date: Fri, 4 Oct 2024 11:47:25 +0200 Subject: [PATCH 5/5] PR feedback & fix animation --- addon/components/layout/side-hover-panel.ts | 5 ++++- .../components/u-edit/shared-triggers/modals/image-upload.ts | 2 +- .../{side-hover-panel/component.js => side-hover-panel.js} | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) rename app/components/layout/{side-hover-panel/component.js => side-hover-panel.js} (64%) diff --git a/addon/components/layout/side-hover-panel.ts b/addon/components/layout/side-hover-panel.ts index 5a50738a..081d1d8e 100644 --- a/addon/components/layout/side-hover-panel.ts +++ b/addon/components/layout/side-hover-panel.ts @@ -1,5 +1,6 @@ import Component from '@glimmer/component'; import { action } from '@ember/object'; +import { later } from '@ember/runloop'; interface SideHoverPanelArgs { side: string; @@ -58,7 +59,9 @@ export default class SideHoverPanel extends Component { this.hoverPanel.classList.add('animate'); } - this.hoverPanel.classList.add(this.side + '_transform'); + later(() => { + this.hoverPanel!.classList.add(this.side + '_transform'); + }, 0); if (this.args.backdropAction) { this.panelBackdrop = element.querySelector('.panel-backdrop'); diff --git a/addon/components/u-edit/shared-triggers/modals/image-upload.ts b/addon/components/u-edit/shared-triggers/modals/image-upload.ts index 78de6c6a..6981f13b 100644 --- a/addon/components/u-edit/shared-triggers/modals/image-upload.ts +++ b/addon/components/u-edit/shared-triggers/modals/image-upload.ts @@ -6,7 +6,7 @@ export default class UEditImageUploadComponent extends UEDitFileUploader { fileUploadRules: FileValidator[] = [ { type: 'filetype', - value: ['jpg', 'jpeg', 'png', 'gif'] + value: ['image', 'gif'] } ]; } diff --git a/app/components/layout/side-hover-panel/component.js b/app/components/layout/side-hover-panel.js similarity index 64% rename from app/components/layout/side-hover-panel/component.js rename to app/components/layout/side-hover-panel.js index 471f1643..3bef1cac 100644 --- a/app/components/layout/side-hover-panel/component.js +++ b/app/components/layout/side-hover-panel.js @@ -1 +1 @@ -export { default } from '@upfluence/ember-upf-utils/components/layout/side-hover-panel/component'; +export { default } from '@upfluence/ember-upf-utils/components/layout/side-hover-panel';