Updated email newsletter settings
- Added toggle to disable email newsletters
- Hides email related UI when email is completely turned off
- Rearranged email newsletter settings
- Added publish-menu preview in
- Changed default-recipients setting
- Updated publish-menu to show Publish as default action
- Removed the confirmation modal during publishing when no emails are intended to be sent
No issue
- Authors don't need access to staff page and don't need to see breadcrumbs on their profile page
- There's enough space in the side navigation for the post views to be visible by default
no issue
- ran the `ember-native-class-codemod` codemod to convert just the route classes to native class syntax and performed some minor manual cleanup
- modern Ember uses native classes rather than EmberObject-based objects, this brings us closer to normalizing our code style across the codebase
- skipped the Application route as that requires deeper testing with a replacement for the `ShortcutsRoute` mixin
no issue
Mixins are deprecated in Ember so we want to remove their usage. The `CurrentUserSettings` mixin was used in Route files to provide `transitionAuthor()` (that also transitions contributors) and `transitionEditor()` methods so the the consuming route could use them to prevent access to authors/editors. In practice the only reason this was used was to prevent access to admin-only routes.
- added an `AdminRoute` class that inherits from our `AuthenticatedRoute` class
- when any route inherits from this class it will only allow access to admins and owners, any other user will be redirected to the home screen (dashboard or site depending on permissions)
- updated all of our admin-only routes to use the new `AdminRoute`
- allowed for removal of `CurrentUserSettings` mixin usage
- allowed for `beforeModel()` hooks to be removed from consuming routes in many cases
- some admin-only routes were extending/inheriting directly from Ember's `Route` based on the assumption that the router hierarchy would have a parent route perform the redirect. Those have also been switched to `AdminRoute` for consistency and to prevent accidentally making them available if the router hierarchy changes
- `/#/settings` does not use the `AdminRoute` so that it can redirect to the current user's setting page for non-admin users
- removed `CurrentUserSettings` mixin file
- cleaned up unnecessary computed property and function used for redirect-when-disabled in the Zapier route
no issue
- the controllers and templates for the old theme setting screens have been removed already but the route files had been missed in the cleanup
refs https://github.com/TryGhost/Team/issues/559
- switched to new ember-promise-modals pattern
- removed controller and template in favor of opening modals directly from the route
- removed unused `mousedown` event handlers - they are only necessary when an input blur would trigger validation errors
- fixed Enter key not triggering create action by adding an `{{on-key "Enter"}}` event handler to the name input
- fixed scroll not resetting to top of integrations screens when navigating between them by adding `{{scroll-top}}` element modifier to the main content sections
refs https://github.com/TryGhost/Team/issues/1164
- removed flag and labs screen toggle
- removed all conditionals
- removed all old/unused route/controller/component files
- renamed labs components and classes to non-labs naming
no issue
When we were given a source+ref we were using that to find a theme object from the built-in list of marketplace themes and if it wasn't found redirecting to the change-theme screen. That redirect didn't need to happen because we only need the `ref` and can determine the theme name from that.
- passed `ref` through to the install modal as a data argument
- updated install modal to get theme name from passed in theme or extracted from passed in `ref` when theme is not known
- adjusted "isDefaultTheme" so it always checks against Casper rather than using the `ref: 'default'` value from the list of marketplace themes
no refs
- access to membership settings is restricted to owners and admins as contributors/authors cannot perform any actions on the page
- redirects non owners/admins back to site when trying to access membership settings via URL
no issue
The marketplace still uses the `/settings/theme/install` route but that was removed as part of the redesign for design settings.
- added `settings.design.change-theme.install` route that uses the newer theme install modal
- requires backing controller for query param support despite no template being rendered
- uses the `change-theme` controller's official theme list to fetch theme details based on query param `ref`
- added `settings.change-theme` route that lives on the old `/settings/theme/install` path and redirects to the new install route
- commented out the old theme settings routes ready for full cleanup/removal
no issue
- moved navigation settings tests from old settings/design tests to a separate file and unskipped them
- added happy-path acceptance tests for
- rendering design screen
- installing an official theme from the themes list
- uploading a custom theme
no issue
We want to automatically show brand settings expanded in the design menu when the active theme has no custom theme settings, in order to do that without causing visual noise/jank we need to ensure that we have all the data we need up-front before the design menu is rendered.
- optimized `customThemeSettings` loading behaviour
- `.load()` will now only perform a fetch if settings have not previously been loaded so it can be called without causing unnecessary waits
- `.reload()` will force a clear+refetch of the settings - called by `themeManagement.activate()` after successfully changing a theme
- moved fetching of theme settings from the design menu constructor to the `settings.design` route's `model()` hook
- means the app will wait for loading to finish before showing any of the design settings screen so we can guarantee the data we need is available
- moved update of preview html from the design menu constructor to the design settings route as it's a more appropriate place to find screen setup/loading behaviour
refs https://github.com/TryGhost/Team/issues/1149
- uses `willTransition` action rather than `deactivate` hook because we also want to close the table when navigating to the theme demo child routes
refs https://github.com/TryGhost/Team/issues/1149
- `customThemeSettings.rollback()` was not performing the correct job, changed to rollback attributes on each model rather than resetting everything to empty
- moved leave confirmation handling to the `settings.design.index` route so that it's always called when moving to the change-theme route, previously with the behaviour on the main `settings.design` route the willtransition/deactivate was not called when expected because that route is still active when on `settings.design.change-theme`
refs https://github.com/TryGhost/Team/issues/1130
- added new route for viewing themes so back/forward buttons can be used
- takes theme name as a parameter
- opens a fullscreen modal with an iframe containing the theme demo
- changed installable themes list to link to new route
- swapped `previewUrl` in theme data to point at the real demo rather than the ghost.org demo page
refs https://github.com/TryGhost/Team/issues/1130
- match latest design where the theme table is under an "advanced" toggle on the change-theme screen rather than a completely separate screen
refs https://github.com/TryGhost/Team/issues/1130
- added link to design sidebar
- dropped change-theme modal and associated route behaviour
- copied basic themes marketplace list into the change-theme controller/template
refs https://github.com/TryGhost/Team/issues/1130
- added `ui.contextualNavMenu` property that when set will switch the main nav menu between components, if it's not set then it will show the default "main" menu component
- added `design` menu sub-component of `gh-nav-menu` ready for use via `contextualNavMenu`
- moved sidebar contents from the design modal into this component
- updated design route to set/reset `ui.contextualNavMenu` to `design` on entering/leaving the route
- all other design routes are sub-routes so this works across all other design screens
- moved base design modal preview into the `settings/design/index` controller/template
- using index means that it's the default screen for `/settings/design` but will be automatically replaced by any other `design.x` routes
- moved `design/advanced` modal content into the `settings.design.advanced` controller/template and removed the modal handling from the route
refs https://github.com/TryGhost/Team/issues/1111
Extracted functionality for listing, downloading, activating, and deleting from the theme controller/template into separate components and services so that they are more composable/reusable in different situations.
- moved theme activation to a new `theme-management` service that uses the `modals` service to open the theme warnings modal or limits upgrade modal as required
- the activate process is a task so that consumers can store a reference to the task instance and cancel it to close any related warning/limit modals (eg, when navigating away from the route or closing the modal that kicked off the process)
- created new-pattern modals for custom theme limit upgrade, theme errors, and delete confirmation so that we can treat them as promises and close where needed from parent
- duplicated theme table component as `<GhThemeTableLabs>` with an actions redesign and a refactor to handle download, activation, and deletion itself making use of the new theme-management service and modals
- fixed some oddities with design modal's transition/modal close handling by simplifying the async behaviour and being more explicit
- added advanced design modal that contains the new theme table component and linked to it from footer of design modal's sidebar
no issue
- appears to be left-over from copy/paste of an earlier screen re-structure
- cleaning up for easier extraction of functionality to new screens / modals
refs https://github.com/TryGhost/Team/issues/559
When modals are re-used across the app it's annoying to have to remember the class names that it uses in every location it's used.
- added a `DEFAULT_MODAL_OPTIONS` object to the modals service that's keyed on the modal to be opened and contains any options that are repeated across every instance
- overrode the `modals.open()` method to merge in the default options before calling `super()`
- updated invocation points of shared modals to remove duplicated class name options
no issue
- opened modal was assigned to `this.customizeModal` but the rest of the code expected `this.offerModal` so correct closing behaviour wasn't gauranteed
refs https://github.com/TryGhost/Team/issues/1111
- added override of the `ember-promise-modals` container component so that it doesn't render the background element when `omitBackground` is passed as an option when opening the modal
- fixes the flicker by not having a dark background transition in whilst the white overlay modal is also transitioning in from transparent->opaque
refs https://github.com/TryGhost/Team/issues/1111
refs https://github.com/TryGhost/Team/issues/1103
- moved customize modal from a link on the design screen to the main design screen
- changed modal design to be a full-screen overlay with side bar that emulates standard Admin design
- added toggled groups of settings in sidebar
- added `{{set-has}}` helper for use in conditionals matching when a Set contains an object
- added grouping of theme settings
- dropped unfinished advanced/change theme modals
refs https://github.com/TryGhost/Team/issues/1070
- split select form component into it's own component so it's cleaner when we get to additional setting types
- added change handler that updates the setting record's value when a new option is selected
- added `.isDirty` to the custom-theme-settings service so we can warn of unsaved changes and revert any changed values when needed
- added save of custom theme settings to the customize design modal's save routine
- added missing `notifications` service import to customize design controller
refs https://github.com/TryGhost/Team/issues/1045
If the customize modal is open and you manually changed the URL, on navigating the modal would close and a transition to the manually entered URL would start but then you'd be transitioned back to `settings.design`.
The problem occurs because `beforeModalClose` is always called when the modal closes causing the redirect.
- added a `hasConfirmed` boolean that is set to `true` when leaving the customize route if there are no unsaved changes or the changes have been confirmed
- skipped the unsaved changes check and redirect in `beforeModalClose` when `hasConfirmed` is true
refs https://github.com/TryGhost/Team/issues/1045
- added tabs to the the customise design modal's sidebar for general settings and theme settings
- copied settings from the existing branding modal plus site description from general settings screen into the general settings tab
- theme settings tab left blank ready for static design
- `saveTask` put on the controller so that we can access it from the route, allowing us to pause modal closing when navigating away (implementation left for later)
refs https://github.com/TryGhost/Team/issues/559
refs https://github.com/TryGhost/Team/issues/1045
- removed need for `{{will-destroy}}` in the modal template by using `willTransition()` in the route that opened the modal instead
- used the property of new modals acting as promises to implement an unsaved changes confirmation modal
- added `confirmUnsavedChanges()` method that opens a "are you sure you want to leave?" modal that is treated as a promise. If the modal is closed by the "Leave" button the promise returns true in which case we rollback the unsaved changes. The modal is returned so that other behaviour can use this method and wait for the confirmation result
- added `willTransition()` route hook that calls `confirmUnsavedChanges()` when there are unsaved changes and will only continue to transition if the "Leave" button is pressed
- added `beforeClose()` hook to the customize modal when opening so that we can prevent the customize modal from closing when "Stay" is clicked in the confirmation modal
- updated `activate()` hook to store the modal instance so it can be closed later
- updated `deactivate()` hook to call `.close()` on the modal instance rather than using private data/methods on the modals service
refs https://github.com/TryGhost/Team/issues/1045
- added new `settings.design.customize` route
- used the route's `activate` and `deactivate` hooks to trigger and close the customize modal
- added `modals/design/customize` component that uses the existing branding modal design without it's contents as a base
- has `{{will-destroy}}` hook that transitions back to the settings screen so the route will update when the modal gets closed
issue https://github.com/TryGhost/Team/issues/857
- The goal is to avoid testing for the owner role only is cases where we should be testing for the owner or admin role
- `isOwner` => `isOwnerOnly`
- `isAdmin` => `isAdminOnly`
- `isOwnerOrAdmin` => `isAdmin` (concerns now both Owner and Admins)
no issue
Having `session.user` return a promise made dealing with it in components difficult because you always had to remember it returned a promise rather than a model and had to handle the async behaviour. It also meant that you couldn't use any current user properties directly inside getters which made refactors to Glimmer/Octane idioms harder to reason about.
`session.user` was a cached computed property so it really made no sense for it to be a promise - it was loaded on first access and then always returned instantly but with a fulfilled promise rather than the underlying model.
Refactoring to a synchronous property that is loaded as part of the authentication flows (we load the current user to check that we're logged in - we may as well make use of that!) means one less thing to be aware of/remember and provides a nicer migration process to Glimmer components. As part of the refactor, the auth flows and pre-load of required data across other services was also simplified to make it easier to find and follow.
- refactored app setup and `session.user`
- added `session.populateUser()` that fetches a user model from the current user endpoint and sets it on `session.user`
- removed knowledge of app setup from the `cookie` authenticator and moved it into = `session.postAuthPreparation()`, this means we have the same post-authentication setup no matter which authenticator is used so we have more consistent behaviour in tests which don't use the `cookie` authenticator
- switched `session` service to native class syntax to get the expected `super()` behaviour
- updated `handleAuthentication()` so it populate's `session.user` and performs post-auth setup before transitioning (handles sign-in after app load)
- updated `application` route to remove duplicated knowledge of app preload behaviour that now lives in `session.postAuthPreparation()` (handles already-authed app load)
- removed out-of-date attempt at pre-loading data from setup controller as that's now handled automatically via `session.handleAuthentication`
- updated app code to not treat `session.user` as a promise
- predominant usage was router `beforeModel` hooks that transitioned users without valid permissions, this sets us up for an easier removal of the `current-user-settings` mixin in the future
no issue
- stripe connect/disconnect functionality has moved to a modal as part of the new membership screen
- removed `settings/members-payments` route and related route/controller/template files
- updated link to stripe connect in product screen to show an alert as a reminder to update to use the new modal (products screens are not usable for now, they'll be worked on again later)
no issue
- added actions for handling close/confirm/cancel of portal settings rather than re-using the route-level leave modal because the portal settings modal does not need any knowledge of the route
- added controller reset that is called when the route is exited to ensure no modals are shown when navigating back to the membership screen
- fixed "cannot set on destroyed" error when portal settings are opened and closed quickly
- removed usage of old `{{action}}` helper - this has been replaced with `{{on}}` and `{{fn}}`
no issue
- simplified query params as they are only used to display a notification
- removed all controller knowledge and associated reset behaviour for query params
- moved notification display from `setupController` to `beforeModel` so the raw query params can be pulled off of the transition object
- removed unused service injections from `<GhMembersEmailSetting>`
- removed unused service injections and properties from members-email controller that were left over from a copy/paste
- converted members-email controller to a native class
- fixed "leave settings" confirmation modal behaviour that wasn't moved across in the the settings screen re-org
refs TryGhost/Team#627
This updates the new Products settings screens to use real data from API for existing Custom Products and Prices to populate them on UI and allow site owners to edit them.
- List all Products of site and allow editing Product name
- List all Prices for a product and allow editing individual Price names
- Add new Prices on a Product
refs https://github.com/TryGhost/Team/issues/627
Wires the real Products data from API to the mock Product settings screen including Product Prices list as well as opening of edit/new price modals. The new Product setting is still behind the developer experiment flag as is under active development, the changes in this commit only allows readonly data but not save/edit upstream.
Co-authored-by: Fabien O'Carroll <fabien@allou.is>
no issue
Unsaved changes handling hadn't been moved across fully to the payments screen when settings were re-jigged meaning changes on the payments screen would make settings dirty and show unsaved changes modal unexpectedly on other screens.
- refactored `members-payments` route to use native classes
- used same unsaved changes pattern as `members-access` route/controller
no issue
- having owner-only access control in the template meant the route was accessible but would show a blank page
- updated access control in the `members-payments` route to redirect admins to the settings index screen and non-admins to the default home screen
refs https://github.com/TryGhost/Team/issues/579
- empty screen ready for signup access and default post access level settings to be moved to
- has unsaved settings changes modal ready
refs https://github.com/TryGhost/Ghost/issues/12608
requires https://github.com/TryGhost/Ghost/pull/12635
- adds `/settings/themes/install` route with `source` and `ref` query params that match the API. Shows a confirmation modal when accessed asking to confirm installation and activation
- does not allow Casper to be installed
- warns if installing the theme will overwrite an existing one
- follows similar process to zip uploads for error handling
- adds install/preview links for Massively in the free themes showcase
Co-authored-by: Sanne de Vries <sannedv@protonmail.com>
no issue
Updated settings navigation to a completely redesigned flow for Ghost 4.0 🎉
Co-authored-by: Kevin Ansfield <kevin@lookingsideways.co.uk>
Co-authored-by: Fabien O'Carroll <fabien@allou.is>
Co-authored-by: Rish <zrishabhgarg@gmail.com>
no issue
Adds new FirstPromoter integration on the integrations page. FirstPromoter enables sites to launch their own members referral program, and integration allows Site admins to directly add their FirstPromoter tracking ID in the settings to enable FirstPromoter script on their site.
no issue
- Adds 2 new email address fields for members in email settings section - support address and reply-to address
- Support address - Is used for member auth emails as well as in themes and Portal for allowing members to contact support.
- Reply-to address - Is used to set `reply-to` address for newsletter emails that allows configuring where member's reply to emails will go
- Disabled from address update for empty value
- Updated success toast message and copy for from/support address update
- Changed section title + description for email addresses
- Added "public" to support email description
refs TryGhost/Ghost#11414
- Restructures member settings in labs, from address gets its own section
- Removes explicit site domain for fromAddress as we allow updating the full address
- Adds new CTA to trigger magic link for updating members from address
- Adds new confirmation modal for email sent to new from address
- Adds notification banner for from address update redirect link
no issue
- After a successful key regeneration, the success message stayed in Zapier integration even on navigating away to different page, this clears up any message state on away transition
no issue
- Adds new regenerate button for refreshing custom integration's admin and content api keys
- Adds new regenerate button for refreshing internal Zapier integration's admin key
- Regenerates content or admin API key after confirmation and shows user new key
no issue
We weren't correctly clearing state for the "display modal" booleans when leaving screens. This meant that it was possible to end up in a state where where every time you access a screen you get the unsaved changes modal
refs. https://github.com/TryGhost/Team/issues/205
Major update to Ghost Admin UI including:
- improved general consistency (typography, colors and contrast, UI components, icons)
- new design for post and pages lists, improved discoverability of filters
- search moved to modal
- account menu is decoupled from ghost logo
- further usability fixes
no issue
- moved `document-title` Route extension's functionality into the `ui` service
- updates the title each time the router service emits a route changed event
- `ui.updateDocumentTitle()` can now be called directly from components rather than the confusing `this.send('updateDocumentTitle')` bubbling behaviour
- refactored the `titleToken` implementation to use the now-formalised `RouteInfo`'s `metadata` field (https://github.com/emberjs/rfcs/blob/master/text/0398-RouteInfo-Metadata.md#appendix-a)
no issue
- removed `styleBody` mixin in favour of using Ember's `buildRouteInfoMetadata` hook and router events in the `ui` service
- refactored separate CSS classes for each unauthenticated route into a single `.unauthenticated-route` class because hiding mobile nav whilst unauthenticated was the only use for body classes
no issue
- many routes were attaching classes to the `<body>` tag via the `StyleBody` mixin but those classes were never used and applied inconsistently throughout the app
no issue
- the new version of our Zapier App uses API Key auth so we need to expose the details on the Zapier integration screen
- extracted `copyTextToClipboard` into a util function
- added `integrationModelHook` method to `settings.integrations` controller to remove duplication in the `settings.integration` and `settings.integration.zapier` routes
- fixed missing "Zapier" title token
no issue
- ran [es5-getter-ember-codemod](https://github.com/rondale-sc/es5-getter-ember-codemod)
- [es5 getters RFC](https://github.com/emberjs/rfcs/blob/master/text/0281-es5-getters.md)
- updates the majority of `object.get('property')` with `object.property` with exceptions:
- `.get('nested.property')` - it's not possible to determine if this is relying on "safe" path chaining for when `nested` doesn't exist
- `.get('config.x')` and `.get('settings.x')` - both our `config` and `settings` services are proxy objects which do not support es5 getters
- this PR is not exhaustive, there are still a number of places where `.get('service.foo')` and similar could be replaced but it gets us a long way there in a quick and automated fashion
no issue
- upgrade to latest `ember-source` and related dependencies including `ember-cli`
- upgrade to latest `ember-mocha` and modern ember testing setup
- https://github.com/emberjs/rfcs/blob/master/text/0268-acceptance-testing-refactor.md
- switch from using global acceptance test helpers and `native-dom-helpers` to using the new `ember-test-helpers` methods
- use [`chai-dom`](https://github.com/nathanboktae/chai-dom) assertions where in some places (still a lot of places in the tests that could use these)
- pin `ember-in-viewport` to 3.0.x to work around incompatibilities between different versions used in `ember-light-table`, `ember-infinity`, and `ember-sticky-element`
- incompatibilities manifested as "Invalid value used as weak map key" errors thrown when using `ember-light-table` (subscribers screen)
- pin `ember-power-datepicker` to unreleased version that contains a move from global acceptance test helpers to modern test helpers
refs https://github.com/TryGhost/Ghost/issues/10137
- when closing the edit webhook modal we were rolling back the changed attributes of the webhook model but not clearing the errors object which meant a validation error was shown when re-opening the edit webhook modal
- add `reset()` method to the webhook edit controller and call that when leaving the edit route instead of only rolling back the changed attributes
closesTryGhost/Ghost#9942
- move custom integrations UI out from behind the developer experiments flag
- put Admin API key and web hook secret fields behind the developer experiments flag
- do not show "unsaved changes" modal when adding/editing a webhook
- fixed all webhooks showing for each custom integration
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
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.
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
closesTryGhost/Ghost#9119, refs TryGhost/Ghost#8483
- Apps - AMP
- Added `leave-settings-modal` component to Settings - Apps - AMP
- Apps - Slack
- Added `leave-settings-modal` component to Settings - Apps - Slack
- Added a `triggerDirtyState` action that will uses a new Array with the input data to trigger the dirty state on the parent settings model
- Apps - Unsplash
- Added `leave-settings-modal` component to Settings - Apps - Unsplash
- Used manual tracking of changes with using a custom `dirtyAttributes` property and a `rollbackValue` to manually rollback the `isActive` attribute on the model
- Code injection
- Added `leave-settings-modal` component to Settings - Code injection
- Design
- Added `leave-settings-modal` component to Settings - Design (only for navigation model)
- Used manual tracking of changes with using a custom `dirtyAttributes`
- Added an additional `updateLabel` action to underlying `gh-navitem` component which gets fired on the `focusOut` event, to detect changes on the label
- Team - User
- Added `leave-settings-modal` component to Team - User
- Used manual tracking of changes with using a custom `dirtyAttributes` to track changes in slug and role properties
no issue
Automated tools, code generators, and editor integrations are increasingly standardising on the import style used in `ember-modules-codemod`. Our import style differed a little with regards to service/controller injection imports which meant we were starting to see inconsistent naming.