Skip to content
This repository was archived by the owner on Nov 28, 2022. It is now read-only.

Commit 72c6004

Browse files
committed
✨ Koenig - Unsplash integration
refs TryGhost/Ghost#9724 - standardised `{{gh-unsplash}}` actions and action arguments to better represent a generic "image source" - added `{{gh-unsplash searchTerm="ghosts"}}` parameter - added `payload` param to `card` definitions used for plus/slash menus so that default payload params can be passed to cards - added a concept of "image selectors" to image card - if a `payload.imageSelector` param is received by the card it will look it up in it's list of known selectors and display the appropriate image selection component - if the card was created with an image selector param and the image selector is closed without selecting an image then the card will be removed - delete image cards during cleanup if they were created via selector but have no src
1 parent f9de6ed commit 72c6004

14 files changed

+96
-40
lines changed

app/components/gh-image-uploader.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ export default Component.extend({
128128
}
129129
},
130130

131-
addUnsplashPhoto(photo) {
132-
this.set('url', photo.urls.regular);
131+
addUnsplashPhoto({src}) {
132+
this.set('url', src);
133133
this.send('saveUrl');
134134
},
135135

app/components/gh-markdown-editor.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,11 @@ export default Component.extend(ShortcutsMixin, {
363363
this.toggleProperty('_showUnsplash');
364364
},
365365

366-
insertUnsplashPhoto(photo) {
366+
insertUnsplashPhoto({src, alt, caption}) {
367367
let image = {
368-
alt: photo.description || '',
369-
url: photo.urls.regular,
370-
credit: `<small>Photo by [${photo.user.name}](${photo.user.links.html}?utm_source=ghost&utm_medium=referral&utm_campaign=api-credit) / [Unsplash](https://unsplash.com/?utm_source=ghost&utm_medium=referral&utm_campaign=api-credit)</small>`
368+
alt,
369+
url: src,
370+
credit: `<small>${caption}</small>`
371371
};
372372

373373
this._insertImages([image]);

app/components/gh-unsplash-photo.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default Component.extend({
1313
zoomed: false,
1414

1515
// closure actions
16-
insert() {},
16+
select() {},
1717
zoom() {},
1818

1919
style: computed('zoomed', function () {
@@ -78,10 +78,10 @@ export default Component.extend({
7878
},
7979

8080
actions: {
81-
insert(event) {
81+
select(event) {
8282
event.preventDefault();
8383
event.stopPropagation();
84-
this.insert(this.get('photo'));
84+
this.select(this.get('photo'));
8585
},
8686

8787
zoom(event) {

app/components/gh-unsplash.js

+21-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ export default Component.extend(ShortcutsMixin, {
1616
shortcuts: null,
1717
tagName: '',
1818
zoomedPhoto: null,
19+
searchTerm: null,
1920

2021
// closure actions
2122
close() {},
22-
insert() {},
23+
select() {},
2324

2425
sideNavHidden: or('ui.{autoNav,isFullScreen,showMobileMenu}'),
2526

@@ -31,6 +32,16 @@ export default Component.extend(ShortcutsMixin, {
3132
};
3233
},
3334

35+
didReceiveAttrs() {
36+
this._super(...arguments);
37+
38+
if (this.searchTerm !== this._searchTerm) {
39+
this.unsplash.updateSearch(this.searchTerm);
40+
}
41+
42+
this._searchTerm = this.searchTerm;
43+
},
44+
3445
didInsertElement() {
3546
this._super(...arguments);
3647
this._resizeCallback = bind(this, this._handleResize);
@@ -63,9 +74,16 @@ export default Component.extend(ShortcutsMixin, {
6374
this.set('zoomedPhoto', null);
6475
},
6576

66-
insert(photo) {
77+
select(photo) {
6778
this.get('unsplash').triggerDownload(photo);
68-
this.insert(photo);
79+
80+
let selectParams = {
81+
src: photo.urls.regular,
82+
alt: photo.description || '',
83+
caption: `Photo by <a href="${photo.user.links.html}?utm_source=ghost&utm_medium=referral&utm_campaign=api-credit">${photo.user.name}</a> / <a href="https://unsplash.com/?utm_source=ghost&utm_medium=referral&utm_campaign=api-credit">Unsplash</a>`
84+
};
85+
this.select(selectParams);
86+
6987
this.close();
7088
},
7189

app/services/unsplash.js

+16-12
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,21 @@ export default Service.extend({
5454
return reject();
5555
},
5656

57+
updateSearch(term) {
58+
if (term === this.get('searchTerm')) {
59+
return;
60+
}
61+
62+
this.set('searchTerm', term);
63+
this._reset();
64+
65+
if (term) {
66+
return this.get('_search').perform(term);
67+
} else {
68+
return this.get('_loadNew').perform();
69+
}
70+
},
71+
5772
retryLastRequest() {
5873
return this.get('_retryLastRequest').perform();
5974
},
@@ -75,18 +90,7 @@ export default Service.extend({
7590

7691
actions: {
7792
updateSearch(term) {
78-
if (term === this.get('searchTerm')) {
79-
return;
80-
}
81-
82-
this.set('searchTerm', term);
83-
this._reset();
84-
85-
if (term) {
86-
return this.get('_search').perform(term);
87-
} else {
88-
return this.get('_loadNew').perform();
89-
}
93+
return this.updateSearch(term);
9094
}
9195
},
9296

app/templates/components/gh-image-uploader.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
{{#if _showUnsplash}}
3030
{{gh-unsplash
31-
insert=(action "addUnsplashPhoto")
31+
select=(action "addUnsplashPhoto")
3232
close=(action (toggle "_showUnsplash" this))
3333
}}
3434
{{/if}}

app/templates/components/gh-markdown-editor.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
{{#if _showUnsplash}}
2525
{{gh-unsplash
26-
insert=(action "insertUnsplashPhoto")
26+
select=(action "insertUnsplashPhoto")
2727
close=(action "toggleUnsplash")}}
2828
{{/if}}
2929

app/templates/components/gh-unsplash-photo.hbs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
{{photo.user.name}}
1616
</a>
1717
</div>
18-
<a class="gh-unsplash-button" href="#" onclick={{action "insert"}}>Insert image</a>
18+
<a class="gh-unsplash-button" href="#" onclick={{action "select"}}>Insert image</a>
1919
</div>
2020
</div>
2121
</div>

app/templates/components/gh-unsplash.hbs

+1-6
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
{{#each unsplash.columns as |photos|}}
4141
<div class="gh-unsplash-grid-column">
4242
{{#each photos as |photo|}}
43-
{{gh-unsplash-photo photo=photo zoom=(action "zoomPhoto") insert=(action "insert")}}
43+
{{gh-unsplash-photo photo=photo zoom=(action "zoomPhoto") select=(action "select")}}
4444
{{/each}}
4545
</div>
4646
{{/each}}
@@ -73,17 +73,12 @@
7373

7474
{{!-- zoomed image overlay --}}
7575
{{#if zoomedPhoto}}
76-
<<<<<<< HEAD
77-
<div class="absolute top-0 right-0 bottom-0 left-0 pr20 pb10 pl20 bg-white" {{action "closeZoom"}}>
78-
{{gh-unsplash-photo photo=zoomedPhoto zoomed=true zoom=(action "closeZoom") insert=(action "insert")}}
79-
=======
8076
<div class="absolute flex justify-center top-0 right-0 bottom-0 left-0 pr20 pb10 pl20 bg-white overflow-hidden" {{action "closeZoom"}}>
8177
{{gh-unsplash-photo
8278
photo=zoomedPhoto
8379
zoomed=true
8480
zoom=(action "closeZoom")
8581
select=(action "select")}}
86-
>>>>>>> 419884354... fixed zoom layout
8782
</div>
8883
{{/if}}
8984
</div>

lib/koenig-editor/addon/components/koenig-card-image.js

+28-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
IMAGE_EXTENSIONS,
77
IMAGE_MIME_TYPES
88
} from 'ghost-admin/components/gh-image-uploader';
9-
import {computed, set} from '@ember/object';
9+
import {computed, set, setProperties} from '@ember/object';
1010
import {htmlSafe} from '@ember/string';
1111
import {isEmpty} from '@ember/utils';
1212
import {run} from '@ember/runloop';
@@ -32,11 +32,21 @@ export default Component.extend({
3232
deselectCard() {},
3333
editCard() {},
3434
saveCard() {},
35+
deleteCard() {},
3536
moveCursorToNextSection() {},
3637
moveCursorToPrevSection() {},
3738
addParagraphAfterCard() {},
3839
registerComponent() {},
3940

41+
imageSelector: computed('payload.imageSelector', function () {
42+
let selector = this.payload.imageSelector;
43+
let imageSelectors = {
44+
unsplash: 'gh-unsplash'
45+
};
46+
47+
return imageSelectors[selector];
48+
}),
49+
4050
counts: computed('payload.{src,caption}', function () {
4151
let wordCount = 0;
4252
let imageCount = 0;
@@ -168,6 +178,23 @@ export default Component.extend({
168178
resetSrcs() {
169179
this.set('previewSrc', null);
170180
this._updatePayloadAttr('src', null);
181+
},
182+
183+
selectFromImageSelector({src, caption, alt}) {
184+
let {payload, saveCard} = this;
185+
let imageSelector, searchTerm;
186+
187+
setProperties(payload, {src, caption, alt, imageSelector, searchTerm});
188+
189+
saveCard(payload, false);
190+
},
191+
192+
closeImageSelector() {
193+
if (!this.payload.src) {
194+
return this.deleteCard();
195+
}
196+
197+
set(this.payload, 'imageSelector', undefined);
171198
}
172199
},
173200

lib/koenig-editor/addon/components/koenig-plus-menu.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default Component.extend({
9696
let range = this._editorRange;
9797

9898
if (item.type === 'card') {
99-
this.replaceWithCardSection(item.replaceArg, range);
99+
this.replaceWithCardSection(item.replaceArg, range, item.payload);
100100
}
101101

102102
this._hideButton();

lib/koenig-editor/addon/components/koenig-slash-menu.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Component from '@ember/component';
22
import layout from '../templates/components/koenig-slash-menu';
33
import {CARD_MENU} from '../options/cards';
4+
import {assign} from '@ember/polyfills';
45
import {computed, set} from '@ember/object';
56
import {copy} from '@ember/object/internals';
67
import {htmlSafe} from '@ember/string';
@@ -91,7 +92,7 @@ export default Component.extend({
9192
itemClicked(item, event) {
9293
let range = this._openRange.head.section.toRange();
9394
let [, ...params] = this._query.split(/\s/);
94-
let payload;
95+
let payload = assign({}, item.payload);
9596

9697
// make sure the click doesn't propagate and get picked up by the
9798
// newly inserted card which can then remove itself because it
@@ -103,7 +104,6 @@ export default Component.extend({
103104

104105
// params are order-dependent and listed in CARD_MENU for each card
105106
if (!isEmpty(item.params) && !isEmpty(params)) {
106-
payload = {};
107107
item.params.forEach((param, i) => {
108108
payload[param] = params[i];
109109
});

lib/koenig-editor/addon/options/cards.js

+8-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ export default [
88
createComponentCard('embed', {hasEditMode: false, deleteIfEmpty: 'payload.html'}),
99
createComponentCard('hr', {hasEditMode: false, selectAfterInsert: false}),
1010
createComponentCard('html', {deleteIfEmpty: 'payload.html'}),
11-
createComponentCard('image', {hasEditMode: false}),
11+
createComponentCard('image', {hasEditMode: false, deleteIfEmpty(card) {
12+
return card.payload.imageSelector && !card.payload.src;
13+
}}),
1214
createComponentCard('markdown', {deleteIfEmpty: 'payload.markdown'})
1315
];
1416

@@ -89,8 +91,11 @@ export const CARD_MENU = [
8991
iconClass: 'kg-card-type-unsplash',
9092
matches: ['unsplash'],
9193
type: 'card',
92-
replaceArg: 'embed',
93-
params: ['url']
94+
replaceArg: 'image',
95+
params: ['searchTerm'],
96+
payload: {
97+
imageSelector: 'unsplash'
98+
}
9499
},
95100
{
96101
label: 'Vimeo',

lib/koenig-editor/addon/templates/components/koenig-card-image.hbs

+7
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,11 @@
7171
placeholder="Type caption for image (optional)"
7272
}}
7373
{{/if}}
74+
75+
{{#if imageSelector}}
76+
{{component imageSelector
77+
searchTerm=payload.searchTerm
78+
select=(action "selectFromImageSelector")
79+
close=(action "closeImageSelector")}}
80+
{{/if}}
7481
{{/koenig-card}}

0 commit comments

Comments
 (0)