Skip to content

Commit

Permalink
Merge pull request #72 from speee/deprecate-dialog-components
Browse files Browse the repository at this point in the history
Output warning about deprecated dialog components
  • Loading branch information
Yuki Hattori authored Oct 15, 2019
2 parents 7cd2fd0 + 23d4347 commit aa0c7e9
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 30 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## [Unreleased]

### Deprecated

- Output warning about deprecated dialog components ([#72](https://github.com/speee/jsx-slack/pull/72))

## v0.10.2 - 2019-10-11

### Fixed
Expand Down
2 changes: 2 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module.exports = {
],
coveragePathIgnorePatterns: ['/node_modules/', '.*\\.d\\.ts'],
coverageThreshold: { global: { lines: 95 } },
resetMocks: true,
restoreMocks: true,
testEnvironment: 'node',
testRegex: '(/(test|__tests__)/(?![_.]).*|(\\.|/)(test|spec))\\.[jt]sx?$',
transform: { ...tsjPreset.transform },
Expand Down
3 changes: 2 additions & 1 deletion src/dialog/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface DialogElementProps {
title?: string
}

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const validateElement = (props: DialogElementProps) => {
if (props.label.length > 48)
throw new DialogValidationError(
Expand Down Expand Up @@ -47,7 +48,7 @@ export const validateElement = (props: DialogElementProps) => {
return { hint }
}

/** @deprecated A classic dialog support was deprecated in favor of Slack Modals. Please migrate into <Modal> container provided by main entrypoint. */
/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const Dialog: JSXSlack.FC<DialogProps> = props => {
let { submitLabel } = props
let stateJSON
Expand Down
2 changes: 1 addition & 1 deletion src/dialog/Input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type InputProps =

type InputElementInternal = HiddenInputProps | SubmitInputProps

// <Input> has an interface to keep compatibility with HTML as possible.
/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const Input: JSXSlack.FC<InputProps> = props => {
let subtype: TextProps['subtype'] | undefined

Expand Down
6 changes: 6 additions & 0 deletions src/dialog/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ const generateFragment = (
return fragment
}

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const SelectFragment: JSXSlack.FC<SelectFragmentProps> = props => {
const opts = filter(props.children)

Expand Down Expand Up @@ -190,6 +191,7 @@ export const SelectFragment: JSXSlack.FC<SelectFragmentProps> = props => {
}
}

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const Select: JSXSlack.FC<SelectProps> = props => (
<ObjectOutput<StaticSelectElement>
{...baseProps(props)}
Expand All @@ -198,6 +200,7 @@ export const Select: JSXSlack.FC<SelectProps> = props => (
/>
)

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const ExternalSelect: JSXSlack.FC<ExternalSelectProps> = props => {
const initial = (() => {
if (props.initialOption) {
Expand Down Expand Up @@ -225,6 +228,7 @@ export const ExternalSelect: JSXSlack.FC<ExternalSelectProps> = props => {
)
}

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const UsersSelect: JSXSlack.FC<UsersSelectProps> = props => (
<ObjectOutput<UsersSelectElement>
{...baseProps(props)}
Expand All @@ -233,6 +237,7 @@ export const UsersSelect: JSXSlack.FC<UsersSelectProps> = props => (
/>
)

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const ConversationsSelect: JSXSlack.FC<
ConversationsSelectProps
> = props => (
Expand All @@ -243,6 +248,7 @@ export const ConversationsSelect: JSXSlack.FC<
/>
)

/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point. */
export const ChannelsSelect: JSXSlack.FC<ChannelsSelectProps> = props => (
<ObjectOutput<ChannelsSelectElement>
{...baseProps(props)}
Expand Down
1 change: 1 addition & 0 deletions src/dialog/Textarea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export type TextareaElement = Pick<
| 'value'
> & { type: 'textarea' }

/** @deprecated A classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by main entrypoint. */
export const Textarea: JSXSlack.FC<TextareaProps> = props => {
const validated = validateElement(props)
const maxLength = coerceToInteger(props.maxLength)
Expand Down
1 change: 1 addition & 0 deletions src/dialog/error.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @deprecated Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Modal's constraint is not so much stricter as dialog so we don't provide an error object for the modal now. */
export class DialogValidationError extends Error {
public constructor(message?: string) {
super(message)
Expand Down
4 changes: 4 additions & 0 deletions src/dialog/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export * from './components'
export { DialogValidationError } from './error'

console.warn(
'[DEPRECATION WARNING] Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point.'
)
90 changes: 62 additions & 28 deletions src/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,43 +61,77 @@ const render = (parsed: unknown) => {
}

// Resolve built-in components
const resolveComponent = (target: unknown, context: any = undefined) => {
if (!(typeof target === 'object' && target)) return target

const node = target as VirtualNode
let { type } = node
// TODO: Please remove in v1. This logic should not be required when the deprecated dialog was removed.
const resolveComponent = (t: unknown) => {
let usingDeprecatedDialog = false

const resolveComponentInner = (target: unknown, context: any) => {
if (!(typeof target === 'object' && target)) return target

const node = target as VirtualNode
let { type } = node

if (typeof type === 'string') {
if (
type.startsWith('Dialog.') &&
Object.prototype.hasOwnProperty.call(dialogComponents, type.slice(7))
) {
// `Dialog.` prefix
type = dialogComponents[type.slice(7)]
} else if (
context &&
Object.prototype.hasOwnProperty.call(context, type)
) {
// Resolve from current context
type = context[type]
} else if (
Object.prototype.hasOwnProperty.call(blockKitComponents, type)
) {
// Block Kit (default)
type = blockKitComponents[type]
} else if (Object.prototype.hasOwnProperty.call(dialogComponents, type)) {
// Dialog (when not resolved in others)
type = dialogComponents[type]
}
}

if (typeof type === 'string') {
// Detect deprecated dialog
if (
type.startsWith('Dialog.') &&
Object.prototype.hasOwnProperty.call(dialogComponents, type.slice(7))
!Object.values(blockKitComponents).includes(type) &&
Object.values(dialogComponents).includes(type)
) {
// `Dialog.` prefix
type = dialogComponents[type.slice(7)]
} else if (context && Object.prototype.hasOwnProperty.call(context, type)) {
// Resolve from current context
type = context[type]
} else if (Object.prototype.hasOwnProperty.call(blockKitComponents, type)) {
// Block Kit (default)
type = blockKitComponents[type]
} else if (Object.prototype.hasOwnProperty.call(dialogComponents, type)) {
// Dialog (when not resolved in others)
type = dialogComponents[type]
usingDeprecatedDialog = true
}
}

let childrenContext: any = context
let childrenContext: any = context

if (!childrenContext) {
if (type === blockKitComponents.Blocks) {
childrenContext = blockKitComponents
}
if (type === dialogComponents.Dialog) {
childrenContext = dialogComponents
}
}

if (!childrenContext) {
if (type === blockKitComponents.Blocks) childrenContext = blockKitComponents
if (type === dialogComponents.Dialog) childrenContext = dialogComponents
return {
type,
props: node.props,
children: node.children.map(c =>
resolveComponentInner(c, childrenContext)
),
}
}

return {
type,
props: node.props,
children: node.children.map(c => resolveComponent(c, childrenContext)),
const result = resolveComponentInner(t, undefined)

if (usingDeprecatedDialog) {
console.warn(
'[DEPRECATION WARNING] Classic dialog support was deprecated in favor of Slack Modals and will remove in v1. Please migrate into Modal provided by the main entry point.'
)
}

return result
}

const parse = (template: TemplateStringsArray, ...substitutions: any[]) => {
Expand Down
14 changes: 14 additions & 0 deletions test/tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ import JSXSlack, {
} from '../src/index'

describe('Tagged template', () => {
let warnSpy: jest.SpyInstance

beforeEach(() => {
warnSpy = jest.spyOn(console, 'warn')
})

it('allows converting Block Kit JSX to JSON without transpiler', () => {
const count = 2
const template = jsxslack`
Expand Down Expand Up @@ -66,6 +72,7 @@ describe('Tagged template', () => {
</Blocks>
)
)
expect(warnSpy).toBeCalledTimes(0)
})

it('allows converting dialog JSX to JSON without transpiler', () => {
Expand Down Expand Up @@ -98,6 +105,7 @@ describe('Tagged template', () => {
</Dialog>
)
)
expect(warnSpy).toBeCalledTimes(1)
})

it('can use imported components through interpolation', () => {
Expand All @@ -114,6 +122,7 @@ describe('Tagged template', () => {
<${Input} type="submit" value="Submit dialog" />
<//>
`).toMatchSnapshot()
expect(warnSpy).toBeCalledTimes(1)
})

it('can use fragmented options in <Select>', () => {
Expand Down Expand Up @@ -143,6 +152,7 @@ describe('Tagged template', () => {
</Blocks>
)
)
expect(warnSpy).toBeCalledTimes(0)
})

it('can use interpolations through conditional rendering', () => {
Expand All @@ -162,6 +172,7 @@ describe('Tagged template', () => {
</Blocks>
)
)
expect(warnSpy).toBeCalledTimes(0)
})

it('has same decode behavior compatible with JSX for HTML entities', () => {
Expand Down Expand Up @@ -280,6 +291,9 @@ describe('Tagged template', () => {
</Dialog>
)
)

// Warn 3 times by each components
expect(warnSpy).toBeCalledTimes(3)
})
})
})

0 comments on commit aa0c7e9

Please sign in to comment.