Skip to content

Commit

Permalink
Merge pull request #1139 from interval/title-to-loading
Browse files Browse the repository at this point in the history
Change `title` prop to `label` for consistency in `io.display.grid` and `ctx.loading` APIs
  • Loading branch information
jacobmischka authored Mar 15, 2023
2 parents a10d02f + 96a618b commit c949f42
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 37 deletions.
4 changes: 2 additions & 2 deletions src/classes/IOClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ export class IOClient {
/**
* Displays data in a grid layout.
*
* Grid items can include a title, description, image, and options menu, and can optionally link to another page, action, or external URL.
* Grid items can include a label, description, image, and options menu, and can optionally link to another page, action, or external URL.
*
* Grid item size can be controlled using the idealColumnWidth property. Interval will calculate a column width that is as close as possible to that number while factoring in gutter size and window width.
*
Expand Down Expand Up @@ -1082,7 +1082,7 @@ export class IOClient {
* },
* ],
* renderItem: row => ({
* title: row.album,
* label: row.album,
* description: row.artist,
* image: {
* url: row.imageUrl,
Expand Down
29 changes: 16 additions & 13 deletions src/classes/TransactionLoadingState.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import { LoadingOptions, LoadingState } from '../internalRpcSchema'
import {
BackwardCompatibleLoadingOptions,
BackwardCompatibleLoadingState,
} from '../internalRpcSchema'
import Logger from './Logger'

export interface TransactionLoadingStateConfig {
logger: Logger
send: (loadingState: LoadingState) => Promise<void>
send: (loadingState: BackwardCompatibleLoadingState) => Promise<void>
}

export default class TransactionLoadingState {
#logger: Logger
#sender: TransactionLoadingStateConfig['send']
#state: LoadingState | undefined
#state: BackwardCompatibleLoadingState | undefined
#sendTimeout: NodeJS.Timeout | null = null
#sendTimeoutMs = 100

Expand Down Expand Up @@ -37,21 +40,21 @@ export default class TransactionLoadingState {
}

/**
* Kicks off a loading spinner to provide context during any long-running action work. Can also be called with a single string argument as the title, or with no arguments to display only a spinner.
* Kicks off a loading spinner to provide context during any long-running action work. Can also be called with a single string argument as the label, or with no arguments to display only a spinner.
*
* **Usage:**
*
*```typescript
* await ctx.loading.start({
* title: "Reticulating splines...",
* label: "Reticulating splines...",
* });
*
* await ctx.loading.start("Title only shorthand");
* await ctx.loading.start("Label only shorthand");
*```
*/
async start(options?: string | LoadingOptions) {
async start(options?: string | BackwardCompatibleLoadingOptions) {
if (typeof options === 'string') {
options = { title: options }
options = { label: options }
} else if (options === undefined) {
options = {}
}
Expand All @@ -71,24 +74,24 @@ export default class TransactionLoadingState {
*
*```typescript
* await ctx.loading.start({
* title: "Something is loading",
* label: "Something is loading",
* description: "Mapping all the things",
* });
*
* await ctx.loading.update({
* title: "Something is loading",
* label: "Something is loading",
* description: "Now reducing all the things",
* });
*```
*/
async update(options?: string | LoadingOptions) {
async update(options?: string | BackwardCompatibleLoadingOptions) {
if (!this.#state) {
this.#logger.warn('Please call `loading.start` before `loading.update`')
return this.start(options)
}

if (typeof options === 'string') {
options = { title: options }
options = { label: options }
} else if (options === undefined) {
options = {}
}
Expand All @@ -109,7 +112,7 @@ export default class TransactionLoadingState {
*
*```typescript
* await ctx.loading.start({
* title: "Migrating users",
* label: "Migrating users",
* description: "Enabling edit button for selected users",
* itemsInQueue: 100,
* });
Expand Down
5 changes: 4 additions & 1 deletion src/components/displayGrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ type PublicProps<Row = any> = Omit<
T_IO_PROPS<'DISPLAY_GRID'>,
'data' | 'totalRecords' | 'isAsync'
> & {
renderItem: (row: Row) => GridItem
renderItem: (row: Row) => GridItem & {
/** @deprecated Please use `label` instead. */
title?: string | null
}
} & (
| {
data: Row[]
Expand Down
18 changes: 9 additions & 9 deletions src/examples/basic/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const dogs = new Action({
data,
idealColumnWidth: 200,
renderItem: row => ({
title: row.name,
label: row.name,
description: row.description,
route: 'tables/display_table',
image: {
Expand All @@ -49,7 +49,7 @@ export const tiktoks = new Action({
.fill(null)
.map((_, i) => ({
id: i,
title: `video from ${faker.internet.userName()}`,
label: `video from ${faker.internet.userName()}`,
description: faker.date.past().toLocaleString(),
image: faker.image.animals(1080 / 4, 1920 / 4, true),
}))
Expand All @@ -58,7 +58,7 @@ export const tiktoks = new Action({
data,
idealColumnWidth: 220,
renderItem: row => ({
title: row.title,
label: row.label,
description: row.description,
image: {
url: row.image,
Expand Down Expand Up @@ -86,7 +86,7 @@ export const no_images: IntervalActionHandler = async io => {
.fill(null)
.map((_, i) => ({
id: i,
title: faker.commerce.productName(),
label: faker.commerce.productName(),
description: faker.commerce.price(100, 200, 0, '$'),
}))

Expand Down Expand Up @@ -156,7 +156,7 @@ export const music = new Action({
data,
idealColumnWidth: 240,
renderItem: row => ({
title: row.name,
label: row.name,
description: row.artists,
image: {
url: row.image,
Expand Down Expand Up @@ -206,7 +206,7 @@ export const long_descriptions = new Action({
data,
idealColumnWidth: 300,
renderItem: row => ({
title: row.name,
label: row.name,
description: row.description,
image: {
url: row.image,
Expand All @@ -231,7 +231,7 @@ export const empty_state = new Action({
data: data.slice(0, 0),
idealColumnWidth: 300,
renderItem: row => ({
title: row.name,
label: row.name,
}),
})
},
Expand All @@ -248,9 +248,9 @@ export const async_grid: IntervalActionHandler = async io => {
image: i % 5 === 0 ? null : faker.image.imageUrl(600, 300, 'dog', true),
}))

await io.display.grid<typeof allData[0]>('Display users', {
await io.display.grid<(typeof allData)[0]>('Display users', {
renderItem: row => ({
title: row.name,
label: row.name,
description: row.description,
image: {
url: row.image,
Expand Down
8 changes: 4 additions & 4 deletions src/examples/basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ const interval = new Interval({
handler: async () => {
await io.display.heading('Hello from display')
await ctx.loading.start({
title: 'Waiting for external system',
label: 'Waiting for external system',
})

await sleep(2000)
Expand Down Expand Up @@ -1134,7 +1134,7 @@ const interval = new Interval({
}

await ctx.loading.start({
title: 'Fetching users...',
label: 'Fetching users...',
description: 'This may take a while...',
})
await sleep(1500)
Expand Down Expand Up @@ -1483,7 +1483,7 @@ const interval = new Interval({
}

await ctx.loading.start({
title: 'Updating users',
label: 'Updating users',
itemsInQueue: users.length,
})
for (const _ of users) {
Expand All @@ -1499,7 +1499,7 @@ const interval = new Interval({
loading_dos: async () => {
const itemsInQueue = 100_000
await ctx.loading.start({
title: 'Migrating users',
label: 'Migrating users',
description: 'There are a lot, but they are very fast',
itemsInQueue,
})
Expand Down
23 changes: 18 additions & 5 deletions src/internalRpcSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,25 @@ export const actionEnvironment = z.enum(['live', 'development'])
export type ActionEnvironment = z.infer<typeof actionEnvironment>

export const LOADING_OPTIONS = z.object({
title: z.string().optional(),
label: z.string().optional(),
description: z.string().optional(),
itemsInQueue: z.number().int().optional(),
})

const LOADING_STATE = z.object({
title: z.string().optional(),
label: z.string().optional(),
description: z.string().optional(),
itemsInQueue: z.number().int().optional(),
itemsCompleted: z.number().int().optional(),
})

const BACKWARD_COMPATIBLE_LOADING_STATE = LOADING_STATE.merge(
z.object({
/** @deprecated in favor of `label` (for real this time) */
title: z.string().optional(),
})
)

const SDK_ALERT = z.object({
minSdkVersion: z.string(),
severity: z.enum(['INFO', 'WARNING', 'ERROR']),
Expand All @@ -58,7 +65,14 @@ const SDK_ALERT = z.object({
export type SdkAlert = z.infer<typeof SDK_ALERT>

export type LoadingOptions = z.input<typeof LOADING_OPTIONS>
export type BackwardCompatibleLoadingOptions = LoadingOptions & {
/** @deprecated Please use `label` instead. */
title?: string
}
export type LoadingState = z.input<typeof LOADING_STATE>
export type BackwardCompatibleLoadingState = z.input<
typeof BACKWARD_COMPATIBLE_LOADING_STATE
>

export const ACCESS_CONTROL_DEFINITION = z.union([
z.literal('entire-organization'),
Expand Down Expand Up @@ -308,10 +322,9 @@ export const wsServerSchema = {
},
SEND_LOADING_CALL: {
inputs: z.intersection(
LOADING_STATE,
BACKWARD_COMPATIBLE_LOADING_STATE,
z.object({
transactionId: z.string(),
label: z.string().optional(),
skipClientCall: z.boolean().optional(),
})
),
Expand Down Expand Up @@ -480,7 +493,7 @@ export const clientSchema = {
.object({
transactionId: z.string(),
})
.merge(LOADING_STATE),
.merge(BACKWARD_COMPATIBLE_LOADING_STATE),
returns: z.boolean(),
},
LOG: {
Expand Down
16 changes: 13 additions & 3 deletions src/ioSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ export const internalTableColumn = z.object({
})

export const gridItem = z.object({
title: z.string().nullable().optional(),
label: z.string().nullable().optional(),
description: z.string().nullable().optional(),
image: z
.object({
Expand All @@ -329,13 +329,23 @@ export const gridItem = z.object({
params: serializableRecord.optional(),
})

export const backwardCompatibleGridItem = gridItem.merge(
z.object({
// @deprecated in favor of label
title: z.string().nullable().optional(),
})
)

export const internalGridItem = z.object({
data: gridItem,
data: backwardCompatibleGridItem,
key: z.string(),
filterValue: z.string().optional(),
})

export type GridItem = z.infer<typeof gridItem>
export type GridItem = z.input<typeof gridItem>
export type BackwardCompatibleGridItem = z.input<
typeof backwardCompatibleGridItem
>
export type InternalGridItem = z.infer<typeof internalGridItem>

const searchResult = z.object({
Expand Down

0 comments on commit c949f42

Please sign in to comment.