requires https://github.com/TryGhost/Ghost/pull/10033
- added `settings.integration.webhooks.edit` route
- `/integrations/:integration_id/webhooks/:webhook_id`
- added error handling to the webhook form modal that copes with the actual errors we get back from the server
- added `event-name` helper to display humanised event names in the webhooks list
- added delete button to the webhooks list and associated confirmation modal
no issue
- display "last seen" time if available for API keys
- use CSS to for hover behaviour instead of JS toggle
- add background to "copy" button so it's visible when on top of key data
- use ember-concurrency tasks instead of actions and used the derived state to show a temporary "copied to clipboard" message in place of the "last seen at" time
no issue
- the webhook form needs to be re-usable for the "edit webhook" modal
- renamed modal
- added logic to adjust the confirm button's text depending on the state of the passed in webhook model
no issue
- `belongsTo` relationships were failing to save on the server correctly because they did not contain the `_id` suffix
- became noticeable when the first standalone `belongsTo` relationship was added to webhooks
- added conditional for special-case `_by` relationships which don't require an additional `_id` when saving to the API
refs https://github.com/TryGhost/Ghost/issues/9865, https://github.com/TryGhost/Ghost/issues/9942
- `integration`, `api-key`, and `webhook` models and respective mirage mocks
- moves integration routes around to match ember's concept of nested routes (nested routes reflect nested UI not nested URLs)
- adds custom integrations list to integrations screen
- adds custom integration screen
- allow editing of integration details
- show list of webhooks
- webhook creation modal
NB: the `enableDeveloperExperiments` flag needs to be enabled in the `config.development.json` file for the custom integrations UI to be displayed until it's out of development.
refs #9865
- removed all `oauth2` and token-based ESA auth
- added new `cookie` authenticator which handles session creation
- updated the session store to extend from the `ephemeral` in-memory store and to restore by fetching the currently logged in user and using the success/failure state to indicate authentication state
- ESA automatically calls this `.restore()` method on app boot
- the `session` service caches the current-user query so there's no unnecessary requests being made for the "logged in" state
- removed the now-unnecessary token refresh and logout routines from the `application` route
- removed the now-unnecessary token refresh routines from the `ajax` service
- removed `access_token` query param from iframe file downloaders
- changed Ember Data adapters and `ghost-paths` to use the `/ghost/api/v2/admin/` namespace
no issue
- after un-nesting the built-in integration routes they no longer had the automatic redirect for non-admins
- added our non-admin redirect behaviour to all of the integration routes
- added our non-admin redirect behaviour to the Zapier route which didn't even have an authenticated redirect previously
- added acceptance test for Zapier route so verify the new behaviour
- wrapped the Zapier widget `<script>` tag in an "is testing" conditional so that the external script doesn't get loaded during tests
no issue
- integrations index screen no longer needs to reload the settings cache
- individual built-in integration routes should handle their own reloading if necessary (eg, zapier doesn't need any settings so doesn't need a delay or loading template)
- built-in integration routes are no longer nested and so need their own loading templates
no issue
- moves integration routes around to match ember's concept of nested routes (nested routes reflect nested UI not nested URLs)
- sets us up for having a `settings.integrations.new` modal route that sits on top of the index screen
no issue
- old static html design files no longer work because they haven't kept up with changes in app and css structure and no longer represent directions that Ghost is moving towards
- removed in a single commit so that it's still possible to retrieve later if needed
no issue
- we were throttling word count updates but not taking into consideration the editor components could have been destroyed by the time the throttle timeout occurred
closes https://github.com/TryGhost/Ghost/issues/9868
- moved submit action to the `<form>` which allowed removal of the per-input enter key handlers
- changed submit button to trigger the form submit
- improved markup for password managers
- linked labels with inputs
- changed button to a "submit" type and linked it with the form
- added hidden email input at the bottom of the form in case password managers do not take disabled inputs into account
no issue
- PasswordValidator was only adding a function to the base class but it introduced a confusing inheritance hierarchy that's easier to reason about when it's a mixin instead
- swapped the `this.properties =` and `this._super()` calls in the `init` function of `new-user` so that the default can actually be applied
- previously the BaseValidator `init` method was doing `this.properties = []` which meant the default fallback in extended classes wouldn't work
closes https://github.com/TryGhost/Ghost/issues/9852
- Ember was throwing an error because we weren't using `.set` to set properties on the editor component which halted execution whilst the component cards were being re-rendered
closes https://github.com/TryGhost/Ghost/issues/9825
- the <code>`</code> key on German keyboard layouts is a dead key and so does not trigger the typical keyboard events our editor relies on
- added custom keyboard event listeners to watch for specific keyboard event sequences triggered by using the dead key + spacebar to insert a <code>`</code>
- trigger text input handlers when we detect a <code>`</code> insertion
- Linux unfortunately does not trigger events that can be used to track the sequence so this will not work there although it is easier to set up keyboard layouts without dead keys on Linux
- moved modifier key tracking into global event handlers from ember event handlers
- reduce confusion from duplicated event handling
- allows modifier key handlers to fire when keys are pressed without the editor element having focus
no issue
- added `onUploadStart` action to `{{gh-uploader}}` that is triggered when individual files start uploading
- will not be triggered for any files that fail client-side validation
- changed `{{koenig-card-gallery}}` to only add images to the local gallery display when the uploader starts an upload
no issue
- moved all payload building into single function
- only put fully valid images into mobiledoc
- extracted image data reading and width/height reading into a separate function
- fixed re-ordering when deleting an image
no issue
- stubbed `ghostPaths` service did not have the expected `ghostPaths.assetRoot` property that the `gh-profile-image` component started calling `.replace` on in adb0508d2f
refs https://github.com/TryGhost/Ghost/issues/9724
- removed 1px white border on embed card click overlay so that it doesn't cover borders used by certain embeds such as Instagram and Facebook posts
no issue
- dropping IE11 support meant that babel/uglifyjs was able to be clever and inline the image URLs variables directly into the template strings which was then breaking the fingerprint asset rewriting resulting in files having hashes but file references in the JS not having the hash
- removing use of template strings to build the default image URLs prevents the inlining behaviour, letting the asset fingerprint plugin do it's thing correctly
refs https://github.com/TryGhost/Ghost/issues/9724
- `formatMarkdown` was previously changed to return a SafeString but that meant any direct usage of the helper had to account for not dealing with a basic String type
- changed `formatMarkdown` to return a basic String
- modified helper usage of `{{sanitize-html}}` to use triple-curlies
refs https://github.com/TryGhost/Ghost/issues/9744
- adds `routes.yaml` upload using the same UI as the `redirects.json` upload
- upload: `POST /settings/routes/yaml/`
- download: `GET /settings/routes/yaml/`
refs https://github.com/TryGhost/Ghost/issues/9724
- fixed Card menu plus icon's rounded edges
- decreased link toolbar appearance delay
- changing 'H'/'h' toolbar mapping to 'H2'/'H3' and harmonized title font size
refs https://github.com/TryGhost/Ghost/issues/9724
- the "paste url on a selection to make it a link" feature from the main editor was missing in caption inputs
- copied functionality across (shared functionality needs extracting at some point)
refs https://github.com/TryGhost/Ghost/issues/9724
- `clean-basic-html` was being overzealous with it's empty element removal, often contenteditable (especially when pasting) will result in HTML such as `<span> </span>` which was being completely removed
- if an empty element has any spaces in it, replace the element with a textNode containing a single space
refs https://github.com/TryGhost/Ghost/issues/9724
- focus was not being returned to the editor after the Unsplash modal was closed so although the image card looked selected the editor was not responding to any key commands
refs https://github.com/TryGhost/Ghost/issues/9724
- mobiledoc-kit's `key.isPrintable()` returns true for <kbd>Enter</kbd> but in this instance we don't want to capture newlines as printable chars
- swapped insertion of `event.key` for `key.toString()` for better handling of named keys that output characters (eg. when `event.key` === `Enter` which prints `\n`)
refs https://github.com/TryGhost/Ghost/issues/9724
- we call `koenig.cleanup` when setting a post in the editor controller but the call will happen before `componentCards` has been populated so none of our "delete if empty" routines were being run
- calls to `.cleanup` now schedule the cleanup after the next editor render which should mean cards are populated before we try to remove them
refs https://github.com/TryGhost/Ghost/issues/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
refs https://github.com/TryGhost/Ghost/issues/9724
- extract html sanitisation into a Koenig helper `{{sanitise-html}}` (all markdown handling will eventually move into Koenig too)
- render sanitised html in the html card
no issue
- re-org of the text-expansions code meant that the smart hyphens expansion was being picked up before the divider card expansion and blocking it
refs https://github.com/TryGhost/Ghost/issues/9724
- add a `data-kg-allow-clickthrough` attribute so that it's possible to explicitly allow non-input elements to be clicked immediately when clicking on a card
refs https://github.com/TryGhost/Ghost/issues/9724
- added `{{koenig-basic-html-input}}` component
- uses a stripped down version of Koenig
- supports all inline formatting that Koenig supports
- supports inline text expansions
- supports inline key commands
- limited to a single paragraph
- serialises and deserialises from HTML rather than mobiledoc
- updated `{{koenig-caption-input}}` to use `{{koenig-basic-html-input}}`
- updated image and embed cards to calculate word counts correctly for html captions
- bumped Spirit dependency to fix styling of toolbars within the editor canvas
- fixed positioning in toolbar components to account for `parentElement` not necessarily being the closest element to position against
refs https://github.com/TryGhost/Ghost/issues/9724
- selecting the embed card as soon as it's created causes problems with the caption input grabbing focus which interferes with being able to continue typing
- if content exists after the paste move the cursor to the beginning of the next section, otherwise create a blank paragraph and move the cursor into that
refs https://github.com/TryGhost/Ghost/issues/9724
- if a URL is pasted in a blank paragraph, insert an embed card configured to switch immediately to a link if the embed fails
- if <kbd>Shift</kbd> is pressed when pasting insert a linked URL with no auto-embed
- added `payload.linkOnError` handling to the embed card
- if that option is set, immediately convert the embed card section to a linked URL on embed failure
- skip adding an undo step when auto-converting to a URL so that no undo loop is created. Without this an undo would convert from link to embed card which would automatically look up the url then convert back to a link meaning it's impossible to undo back past the URL paste
- ensure that the cursor position doesn't jump if the user has continued writing whilst the oembed lookup is in progress
refs https://github.com/TryGhost/Ghost/issues/9724
- `card.handlesDragDrop` was never accessible, it would have had to be registered through `card.koenigOptions.handlesDragDrop` when the drop handling was first added
- as of cc2e20a486 properties on card components are directly accessible so we can use `card.component.handlesDragDrop` to guard against the editor handling drops on cards that handle their own drops
refs https://github.com/TryGhost/Ghost/issues/9724
- adjust `insertImageCards()` to handle the editor not having an active section
- add `jumpToCard` option to `_scrollCursorIntoView()` so that we can scroll to a card when appropriate
- call `_scrollCursorIntoView()` after dropping images and creating cards
refs https://github.com/TryGhost/Ghost/issues/9724
- fixed image card background colour
- made placeholder illustration for image cards work with Night Shift
- added viewbox prop to `summer.svg` illustration
- bumped ghost-spirit dependency
- fixed link discoverability when spellcheck is on
- fixed list spacing after headings 3-6 and refined list line heights
- added quick transition to format toolbar chiclet
- removed minimum width for image caption
- fixed wide image width in Safari
refs https://github.com/TryGhost/Ghost/issues/9724
- `event.code` represents physical key location rather than the associated key value. Eg, `event.code` could be `NumpadEnter` rather than the expected `Enter` value
- ensure we use `event.key` anywhere that we are acting on the key value so that re-mapped or virtual keys still work as expected
refs https://github.com/TryGhost/Ghost/issues/9724
- when Koenig is active, toggle `ui.isFullscreen` when entering/leaving the editor route
- add `ui.isFullscreen` to the `showNavMenu` CP in the application controller
- when in fullscreen mode, display a "< Stories" link in the editor header
- refine editor header style
refs https://github.com/TryGhost/Ghost/issues/9724
- leaving the editor could result in the plus menu being removed from DOM before teardown has fully cleared up the event handlers resulting in an error being thrown in the mousemove handler where we assumed the element is present
refs https://github.com/TryGhost/Ghost/issues/9724
- word count is displayed in the bottom right of the screen regardless of screen size
- for smaller screen sizes the word count display is adjusted
- minor visual tweaks and refinements
refs https://github.com/TryGhost/Ghost/issues/9724
- removed reading time from word count display, it will be added back later as part of a more comprehensive stats interface
- added background to the bottom right word count so it's still visible when above a full-width image
refs https://github.com/TryGhost/Ghost/issues/9724
- Firefox has a bug that prevents the cursor from moving from one element to another when pressing <kbd>Up</kbd> in certain circumstances
- added workaround that replicates the default behaviour that all other browsers have so that <kbd>Up</kbd> can always move to the previous section
refs https://github.com/TryGhost/Ghost/issues/9724
- add `registerComponent` hook to cards so that `{{koenig-editor}}` can fetch properties from card components directly
- add word count and reading time utilities
- add throttled word count update routine to `{{koenig-editor}}` that walks all sections and counts text words or fetches word/image counts from card components
- add `wordCountDidChange` hook to `{{koenig-editor}}` so that word count + reading time can be exposed
- modify editor controller to update it's own word count property when koenig triggers it's action
- modified the editor template to show reading time + word count next to the post status
no issue
- `staticPages` API param is deprecated in favour of using the `filter` param
- switched `status` query to param to the `filter` param as well for consistency
refs https://github.com/TryGhost/Ghost/issues/9724
- <kbd>Ctrl/Cmd+Enter</kbd> is the shortcut to enter edit mode of a card that has it
- adds <kbd>Ctrl/Cmd+Enter</kbd> as a shortcut to exit edit mode as an addition to <kbd>Escape</kbd> for easier toggling in/out of edit mode
refs https://github.com/TryGhost/Ghost/issues/9724
- ignore the range change which would otherwise close the menu when clicking a (+) next to a different paragraph then the one the cursor is currently on
refs https://github.com/TryGhost/Ghost/issues/9724
- add an overlay to the markdown card for 500ms when entering edit mode to stop extra clicks accidentally triggering toolbar buttons
refs https://github.com/TryGhost/Ghost/issues/9724
- eb865f841f introduced a bug because it expected an event param that is only available when clicking
- add guard to check for `event` presence before attempting to stop propagation
refs https://github.com/TryGhost/Ghost/issues/9724
- the click event from clicking on the /-menu items continued propagating after the card was initialised which meant it was picked up by the card as a "click off the card" so certain cards such as the Markdown/HTML cards would then remove themselves as if they were deselected with empty content
- changed the icon click handler to use the DOM `onclick` syntax so that the click can be captured immediately rather than waiting for it to bubble up to Ember's global event handler
- updated the /-menu `itemClicked` action to use the now-accessible MouseEvent to stop it propagating any further and triggering unwanted card behaviour
refs https://github.com/TryGhost/Ghost/issues/9724
- `element.contains(target)` was not reliably picking up the `<span>` inside the `<button>` element
- added a fallback that searches the event path for the card component's ID
refs https://github.com/TryGhost/Ghost/issues/9724
- `{{koenig-menu-content}}` does not pass any params through when an item is clicked
- move the `params` fetching via the query string from `_performAction()` to `actions.itemClicked` so that it works for both <kbd>Enter</kbd> and icon clicks
refs https://github.com/TryGhost/Ghost/issues/9724
- if the editor was reloaded by changing the post model either through clicking "New story" or using the search from the editor screen the /-menu would stop working
- keep track of the last seen `editor` instance inside `{{koenig-slash-menu}}` and register the `/` text input handler on the new editor instance if it changes
refs https://github.com/TryGhost/Ghost/issues/9724
- add `ember-useragent` package so that we can check the user agent screen for known-incompatible browsers/devices
- show alerts for Edge, mobile browsers, and IE11 when accessing the editor with Koenig enabled
no issue
- ensure at least one SlackIntegration object exists in the slack setting when deserialising
- remove blank SlackIntegration objects when serialising
refs https://github.com/TryGhost/Ghost/issues/9623
- Firefox unlike other browsers triggers `keypress` events for non-printable characters
- use mobiledoc-kit's `Key` class to guard against adding non-printable key values to captions
refs https://github.com/TryGhost/Ghost/issues/9623
- disable `contenteditable` on the main editor element when an input in a card gains focus
- Firefox chokes on inputs inside a `contenteditable` element
- use a MutationObserver inside `{{koenig-card}}` to automatically add event handlers for focus/blur events so that each card is not required to set up handlers and enable/disable content editable manually
- bump Spirit dependency
- remove `user-select: none` styling from `.form-text` for text inputs
- fixes captions and embed inputs in Safari and improves behaviour in Firefox
- add a guard around `getSelection(0)` in the `_scrollCursorIntoView()` method to avoid Safari throwing errors
refs https://github.com/TryGhost/Ghost/issues/9623
- clicks near the HR card when it was selected would trigger immediate deselection putting the cursor into a position where it was not possible to type
- update the guard in the click-to-deselect event handler to match any element contained by the editor rather than only clicks that are directly on the editor element
refs https://github.com/TryGhost/Ghost/issues/9623
- close menu if it's open and the cursor position changes within the document
- closes when you start typing rather than hiding text behind the menu
- watch for arrow keys and close the menu if pressed
- closes when <kbd>Up</kbd> is pressed and the title is selected rather than the cursor being moved within the document
refs https://github.com/TryGhost/Ghost/issues/9623
- move lazy-click handling to a mouseup handler instead of mousedown in `{{koenig-card}}`
- ensure that we don't trigger edit mode on the initial mouseup after a mousedown event has selected the card
refs https://github.com/TryGhost/Ghost/issues/9623
- clicking a card a second time while it is selected can move the invisible cursor to the beginning of a section in which case <kbd>Enter</kbd> would insert a blank paragraph above the card
- when <kbd>Enter</kbd> is pressed and a card is selected, move the cursor to the end of the card section without triggering our cursor change so that the default behaviour will always add a paragraph after the card
refs https://github.com/TryGhost/Ghost/issues/9623
- track the `mousedown` position and switch the `click` handler to a `mouseup` handler
- only trigger the editor focus event if both the `mousedown` and `mouseup` events occur below the editor canvas