Skip to content

Commit

Permalink
feat: UI Extension changes (#34)
Browse files Browse the repository at this point in the history
* feat: UI Extension changes

* chore: Removes pre-release versions

* chore: Updates ContextMenuData to be app-specific

* chore: Adds alpha versions back (for now)

* chore: Adds JSDocs

* chore: Fixes react package types

* chore: Exports headers correctly

* chore: Update core package version

* chore: Removes `includeEmptySpacing` option

* chore: Updates core package version

* chore: Make `emptySpaceImageUrl` optional

* chore: Updates core package version

* chore: Remove pre-release versions
  • Loading branch information
scottlovegrove authored Nov 8, 2022
1 parent de7cada commit f413808
Show file tree
Hide file tree
Showing 25 changed files with 694 additions and 211 deletions.
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/ui-extensions-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@doist/ui-extensions-core",
"version": "3.3.0",
"version": "4.0.0",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions packages/ui-extensions-core/src/doist-card/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ export class SubmitAction extends Action {
@JsonProperty()
data?: PropertyBag

@JsonProperty()
loadingText?: string

protected getJsonTypeName(): string {
return 'Action.Submit'
}
Expand Down
14 changes: 14 additions & 0 deletions packages/ui-extensions-core/src/doist-card/card-elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Action } from './actions'
import { CardElement } from './card-element'
import { ContainerWithNoItems } from './containers'

import type { Props } from './props'
import type {
DoistCardVersion,
FontSize,
Expand Down Expand Up @@ -103,6 +104,19 @@ export class DoistCard extends ContainerWithNoItems {

return result
}

static fromWithItems<T extends DoistCard>(
this: new () => T,
props: Props<T> & { items?: CardElement[] },
): T {
const o = new this()
const { items, ...rest } = props
Object.assign(o, rest)
if (items && items.length > 0) {
items.forEach((item) => o.addItem(item))
}
return o
}
}

@Serializable()
Expand Down
3 changes: 2 additions & 1 deletion packages/ui-extensions-core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './doist-card/'
export * from './doist-card'
export * from './types'
export * from './ui-helpers'
74 changes: 74 additions & 0 deletions packages/ui-extensions-core/src/types/bridges.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Types of actions that the server can invoke on the client via a bridge.
*/
export type DoistCardBridgeActionType = DoistCardBridge['bridgeActionType']

/**
* The notification display type
*/
export type DoistCardNotificationType = 'success' | 'error' | 'info'

/**
* The bridge notification. This should be supplied when the `bridgeActionType` is `display.notification`
*/
export type DoistCardBridgeNotification = {
/**
* The text that should appear in the notification.
*
* NOTE: this should be plain text, Markdown is *not* supported
*/
text: string
type: DoistCardNotificationType
/**
* The action, this should be a URL and is what will be launched when clicked (if provided)
*/
actionUrl?: string
/**
* This is the text that will be displayed as the notification action, clicking it will take you to
* what has been assigned to `actionUrl`
*/
actionText?: string
}

/**
* The bridge action that closes the UI extension within Twist/Todoist.
*/
export type FinishedBridge = {
bridgeActionType: 'finished'
}

/**
* The bridge action that inserts text into the relevant text input field.
*/
export type ComposerAppendBridge = {
bridgeActionType: 'composer.append'
text: string
}

/**
* The bridge action that displays a notification and optional action. The action will open a URL in the browser.
*/
export type DisplayNotificationBridge = {
bridgeActionType: 'display.notification'
notification: DoistCardBridgeNotification
}

/**
* The bridge action that will trigger a sync request in Todoist. The bridge accepts notifications
* for both success, and error, scenarios.
*/
export type RequestTodoistSyncBridge = {
bridgeActionType: 'request.sync'
onSuccessNotification?: DoistCardBridgeNotification
onErrorNotification?: DoistCardBridgeNotification
}

/**
* The bridge represents actions that the server asks the client to invoke locally,
* along with necessary parameters to do so.
*/
export type DoistCardBridge =
| FinishedBridge
| ComposerAppendBridge
| DisplayNotificationBridge
| RequestTodoistSyncBridge
183 changes: 7 additions & 176 deletions packages/ui-extensions-core/src/types/data-exchange.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { DoistCard } from '../doist-card'
import type { DoistCardBridge } from './bridges'
import type { TodoistContext, TodoistContextMenuData } from './todoist'
import type { TwistContext, TwistContextMenuData } from './twist'

/**
* The types of actions that an adaptive card integration can request.
Expand All @@ -21,62 +24,17 @@ export type DoistCardActionParams = Record<string, unknown>
*/
export type DoistCardActionData = Record<string, unknown>

/**
* The different extension types that are currently available.
*/
export type DoistCardExtensionType = 'composer' | 'context-menu' | `settings`

export type TwistContextMenuSource = 'message' | 'thread' | 'comment'

export type TodoistContextMenuSource = 'project' | 'task'

/**
* When a context menu extension is triggered, the data will be sent in the
* `params` field of the `DoistCardAction`. This type will allow you to
* cast that data to something specific.
*/
export type ContextMenuData = {
/**
* The deep link back to the source
*/
url: string
/**
* The id of the source object
*/
sourceId: number
/**
* The content that has been sent with the request. This could be
* a conversation message, thread comment, or thread title
*/
content: string
/**
* The content that has been sent with the request. This could be
* a conversation message, thread comment, or thread title, only this
* has been scrubbed of all markdown formatting.
*/
contentPlain: string
} & (
| {
/**
* The source that made the request to the extension
*/
source: TwistContextMenuSource
/**
* The date the content was posted. For threads, this will be the
* date the thread was created.
*/
postedDate: Date
}
| {
/**
* The source that made the request to the extension
*/
source: TodoistContextMenuSource

/**
* The date the content was posted. For projects, this will be null.
* For tasks this will be the date the task was created.
*/
postedDate?: Date
}
)
export type ContextMenuData = TodoistContextMenuData | TwistContextMenuData

/**
* Represents an action that the user has done on the client.
Expand Down Expand Up @@ -116,94 +74,10 @@ export type DoistCardContextUser = {
email: string
}

/**
* The workspace where the user is currently browsing content.
*/
export type DoistCardContextWorkspace = {
id: number
name: string
}

/**
* The current channel in which the user is browsing content. Is not present in the data if the user is not currently browsing a channel.
*/
export type DoistCardContextChannel = {
id: number
name: string
description: string
}

/**
* The current thread in which the user is browsing content. Is not present in the data if the user is not currently browsing a thread.
*/
export type DoistCardContextThread = {
id: number
title: string
}

/**
* The current conversation in which the user is browsing content. Is not present in the data if the user is not currently browsing a a conversation.
*/
export type DoistCardContextConversation = {
id: number
title: string
}

type IdAndName = { id: number; name: string }

/**
* The current project in which the user is browsing content. Is not present in the data if the user is not currently browsing a project.
*/
export type DoistCardContextProject = IdAndName

/**
* The current label in which the user is browsing content. Is not present in the data if the user is not currently browsing a label.
*/
export type DoistCardContextLabel = IdAndName

/**
* The current filter in which the user is browsing content. Is not present in the data if the user is not currently browsing a filter.
*/
export type DoistCardContextFilter = IdAndName

type Message = {
id: number
content: string
posted: Date
}

export type DoistCardContextMessage = Message

export type DoistCardContextComment = Message

export type Theme = 'light' | 'dark'

export type Platform = 'desktop' | 'mobile'

/**
* Context on which interactions with the adaptive card integration happen.
*/
export type TwistContext = {
workspace: DoistCardContextWorkspace
channel?: DoistCardContextChannel
thread?: DoistCardContextThread
conversation?: DoistCardContextConversation
message?: DoistCardContextMessage
comment?: DoistCardContextComment
}

/**
* Context from Todoist on which interactions with the adaptive card integration happen.
*/
export type TodoistContext = {
/**
* Project may not exist as Todoist could be on Today/Upcoming/Filters
*/
project?: DoistCardContextProject
filter?: DoistCardContextFilter
label?: DoistCardContextLabel
}

export type DoistCardContext = {
user: DoistCardContextUser
theme: Theme
Expand All @@ -226,48 +100,6 @@ export type DoistCardRequest = {
maximumDoistCardVersion: number | undefined
}

/**
* Types of actions that the server can invoke on the client via a bridge.
*/
export type DoistCardBridgeActionType = 'composer.append' | 'finished' | 'display.notification'

/**
* The notification display type
*/
export type DoistCardNotificationType = 'success' | 'error' | 'info'

/**
* The bridge notification. This should be supplied when the `bridgeActionType` is `display.notification`
*/
export type DoistCardBridgeNotification = {
/**
* The text that should appear in the notification.
*
* NOTE: this should be plain text, Markdown is *not* supported
*/
text: string
type: DoistCardNotificationType
/**
* The action, this should be a URL and is what will be launched when clicked (if provided)
*/
actionUrl?: string
/**
* This is the text that will be displayed as the notification action, clicking it will take you to
* what has been assigned to `actionUrl`
*/
actionText?: string
}

/**
* The bridge represents actions that the server asks the client to invoke locally,
* along with necessary parameters to do so.
*/
export type DoistCardBridge = {
bridgeActionType: DoistCardBridgeActionType
text?: string
notification?: DoistCardBridgeNotification
}

/**
* A top-level object representing a response by the server agains the integration client.
*/
Expand All @@ -279,6 +111,5 @@ export type DoistCardResponse = {
export type DoistCardError = {
error: Error
request?: DoistCardRequest
bridge?: DoistCardBridge
bridges?: DoistCardBridge[]
}
3 changes: 3 additions & 0 deletions packages/ui-extensions-core/src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from './bridges'
export * from './data-exchange'
export * from './todoist'
export * from './twist'
Loading

0 comments on commit f413808

Please sign in to comment.