Planning Center application Topbar
npm install @planningcenter/topbarThe shared Planning Center product Topbar
In general, it is responsible for a number of things that are shared across our apps.
- App switcher (via AppsProvider)
- Profile switcher (via ConnectedPeopleProvider)
- Admin notifications inbox dropdown (via NotificationsMenu)
- Platform and/or product announcements (via PlatformAnnouncements and ProductAnnouncements)
To a limited extent, each product can customize the display of these items as they see fit.
For the majority of the products, implementation is very similar.
You can view product-specific examples below.
The global determination of whether the notifications inbox is enabled or disabled is controlled via a People flipper flag.
However, if your app needs to disable the notifications inbox for whatever reason, set window.notificationsDisabled = true when your app renders and we'll honor that setting.
Because settings and flags are cached for one load cycle, it will take a fresh reload from the user to have the disable override to take effect.
New in v7.3 is the admin notifications inbox feature.
Visually, this is a bell in the topbar that, when clicked, will display a dropdown containing notifications from every app in their account.
Because a notification can be sent to a user as they are working on a page, topbar subscribes to a special notifications channel for the current user that provides push updates to the dropdown.
For a handful of reasons (not least of which is because we pay per Jolt connection), if the current page of an app is already using a Jolt connection, topbar would like to piggy-back on that connection for its own subscription.
Note that this connection sharing is entirely optional for the parent app, but strongly encouraged.
If a Jolt connection is not shared with topbar, it will gladly initiate its own connection specifically for its purposes.
To reuse your app's Jolt connection, topbar requires a Promise that resolves into a Jolt client connection.
If nothing is passed—or if a Promise is passed that resolves to undefined or void—topbar will initiate its own connection.
Topbar hooks into pco-page-expired and will disconnect when the session is invalidated (i.e. logged out in a different tab).
This occurs for topbar-created jolt instances as well as jolt instances provided to topbar via the joltPromise prop.
CSRF tokens are invalidated when the session is invalidated.
Non-GET APIv2 requests (i.e. auth/subscribe) require a valid CSRF token and will never succeed in that state.
#### Example
As an example, we'll use what Services has done for the v7.3 alpha.
As a layout partial, they attach two Jolt-related things to window:
1. joltListener (an instance of their own wrapper around the jolt-client library)
1. joltListenerPromise (a jolt-client instance that has gone through (or will go through asynchronously) the connection and authorization process)
``html`
In their Topbar implementation component, they then create the function that provides topbar the required Promise...
`jsx`
const waitForWindowJolt = async () =>
window.joltListenerPromise.then((listener) => {
if (listener && listener.jolt) {
return listener.jolt
}
})
...and passes that function in for the JoltPromise prop to topbar.
Topbar can then use this Promise to determine whether or not it needs to create its own connection or piggyback on one provided.
The implementation details for your app can be decided by you and dependent on your apps current usage of Jolt.
`bash`
yarn add @planningcenter/topbar
`bash`
cd ~/Code/planningcenter/design/planningcenter/topbar
yarn install
yarn dev
The dev script starts a server at http://localhost:9000.
The dev/dev.tsx is the main dev environment component.
In order for the Chat tool to fetch your Stream User, the component needs your planning_center_session cookie.
Visiting the Topbar dev server at people.pco.test:9000 (or at port 9000 on any of the other apps listed in your hosts file) will provide the cookie.
If you are working on a new feature or run into a specific bug in your application and need to inspect the problem locally before publishing, you can use yalc to install and run the Topbar package locally.
To get started:
1. In /topbar: yalc publishyalc add @planningcenter/topbar
2. In your product:
When you make topbar changes, run yalc publish --push to update your product.
When you're done, in your product directory run yalc remove @planningcenter/topbar.
If you are not seeing published updates after running yalc publish --push or things break in your app after running yalc remove @planningcenter/topbar then in your product you will want to be running bin/webpack-dev-server.bin/webpack-dev-server
From experience, we have seen that the People app will automatically reload while running .bin/webpack-dev-server
Unfortunately, in the Services app we have had to restart every time for a change to come in.
This may change depending on what app you're adding your yalc changes to.
The jolt-client library has the ability to log debug information to the console.enableJoltLogging={true}
This functionality is configured when creating a client and is disabled by default.
If you are passing your own Jolt client object into Topbar via props, you can configure it as required before providing it to Topbar.
If you are relying on Topbar to create its own Jolt connection and would like to enable logging, pass as a prop to whichever topbar components you are usingAppsProvider
you are using (/Tasks/Toolbar).
Toolbar lives alongside Topbar on the right side of the viewport. It is responsible for the global concerns of Profile, Help Desk, Tasks, Notifications, and Core Messaging.
Tool implementations are self-contained modules that live in the modules/toolbar/tools/ directory.
A tool module is required to have a named export which adheres to the following ToolbarTool interface.
`ts`
interface ToolbarTool {
component: unknown // A React component. Stronger typing is in the works.
icon: string
name: string
}
- component: the React component that will be rendered into the drawer when the tool is selected.icon
- : the name of the tapestry-react icon that will be rendered as the button in Toolbar.name
- : the formal name of the tool. For now, this is only surfaced for accessibility concerns on the tool's toolbar Button.
The following example implements an example tool using the shared DrawerHeader and DrawerHeading components.
- DrawerHeader handles the placement and styling of the close button.DrawerHeading
- handles the styling of the drawer heading.
`ts
// tool_name.tsx
import { DrawerHeader, DrawerHeading } from "../components"
import { ToolbarTool } from "../types"
function ToolComponent({ closeDrawer }) {
return (
<>
{/ Tool drawer content implementation /}
>
)
}
const ToolName: ToolbarTool = {
component: ToolComponent,
icon: "general.toolbarIconName",
name: "Tool name",
}
export { ToolName }
``
These migration docs will guide you thru the process of updating to recent major releases.
- Migrate to v6
- Migrate to v5
This is a limited history.
Topbar releases often require a coordinated effort across products and no app can stay an outdated version for very long.
So, this CHANGELOG is a little lazy.
If you like history, here are the initial release notes with technical considerations and trade-offs.
- API
- Accounts
- Calendar
- Check-Ins
- Giving
- Groups
- People
- Publishing
- Registrations
- Services