Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Where can I find documentation on JsEvent? #25

Open
pillowfication opened this issue Aug 21, 2023 · 9 comments
Open

Where can I find documentation on JsEvent? #25

pillowfication opened this issue Aug 21, 2023 · 9 comments

Comments

@pillowfication
Copy link

pillowfication commented Aug 21, 2023

Where can I find documentation on the JsEvent method?

declare const JsEvent: (Event: string, item: object, context?: IContext) => Promise<unknown>;

The UI-SDK page only shows how to list all the supported events, but I can't find anything that explains what these events do, their possible options, and their outputs. More specifically, is it possible to specify "FileBrowse" to filter for something like "*.csv" files instead of the default "*.yxmd;*.wmdl;*.yxwz;*.yxmc;*.yxzp;*.yxi;*.yxwg"?

const filePath = await JsEvent('FileBrowse', {})
//                           What goes here? ↑

Or is there an analogous "DirectoryBrowse" event to select directories instead of files, like the built-in Directory tool?

@kingedward35
Copy link
Collaborator

Hey Pillow. In this document it shows how the C# is using the JsEvent method. Maybe this can shed some light on how to use the other arguments to the function. Let me know if that helps.

@pillowfication
Copy link
Author

pillowfication commented Aug 21, 2023

That document only shows usage for the SetConfiguration and GetConfiguration events (and shows the outdated usage). There is also an example for the FileBrowse Event here, but with no arguments, so I don't know if there is support for specifying the file type, or support for multiple files to be selected.

There are still many others supported events that I could not find documentation on.

['SaveExpression', 'SetConfiguration', 'GetConfiguration', 'RequestConfiguration', 'GetInputData', 'Encrypt', 'Decrypt', 'TestExpression', 'FormulaPreview', 'FileBrowse', 'GetFormulaConstants', 'GetFormulaRecentAndSavedExpressions', 'SaveFormulaRecentExpression', 'RenameSavedExpression', 'DeleteSavedExpression', 'OpenHelpPage', 'ConfigureVisualLayout', 'ConfigureCharting', 'GenerateFormulaExpressions', 'ConfigureInsight', 'OpenAddPromoteDialog', 'GetPromoteCredentialsList', 'DeletePromoteCredentialsPrompt', 'GetLockinConnectionStringKeyValue', 'ShowInDbConnectionContextMenu', 'GetFileContents', 'ConvertJupyter', 'GenerateSimpleFormulaExpression', 'AddTableauAlias', 'GetAllTableauAliases', 'GetTableauAlias', 'DeleteTableauAlias', 'DeleteAllTableauAliases', 'GetSparkConnectionType', 'GetRecentColors', 'SaveRecentColor', 'GetAlteryxTempDir', 'NewCallBack', 'InsightDataExists', 'MD5Hash', 'OpenAyxModelModal', 'AddToolsToCanvas', 'CheckFileExits', 'CheckIfFeatureIsLicensed', 'SaveDataToFile', 'GetGoogleAuth', 'GetAzureOAuth', 'GetRefreshAzureOAuth', 'GetSortOptions', 'DeleteCookie', 'SetupConnection', 'DcmRestCall', 'GetGenericOAuth', 'MakeWebRequest', 'RedeemAuthorizationCode', 'OpenUserSettings', 'GetFeatureToggle']

I was hoping there was help for how to use them, instead of guessing what arguments each one takes through trial and error.

@pillowfication
Copy link
Author

pillowfication commented Aug 22, 2023

Seems this 2017 blog post has somehow determined the following known arguments:

JsEvent Arguments Returns
"Encrypt" { text: String } String
"Decrypt" { text: String } String
"FileBrowse" {} String
"FolderBrowse" unsupported unsupported
"GetInputData" { anchorIndex: Number, connectionName: String, numRecs: Number, offset: Number } { fields: { strName: String, strType: String, nSize: String, strSource: String, strDescription: String }[], numRecs: Number, data: Any[][] }
"GenerateFormulaExpressions" {} { FUNCTIONS: Any[], OPERATORS: Any[], CONDITIONALS: Any[] }
"GetFormulaConstants" {} { formulaConstants: Any[], questionConstants: Any[] }
"GetFormulaRecentAndSavedExpressions" ??? ???
"SaveFormulaRecentExpression" { expressionText: String } ???
"SaveExpression" { name: String, expression: String } ???
"DeleteSavedExpression" { expressionName: String } ???
"RenameSavedExpression" { oldName: String, newName: String } ???
"TestExpression" { expression: String, customFields: Any[] } { error: { charPosition: Number, errorMessage: String }, syntaxObject: String }
"FormulaPreview" { connectionName: String, anchorIndex: Number, expressions: { name: String, type: String, expression: String }[] } ???

@kingedward35
Copy link
Collaborator

That is an interesting find. Has that helped with the issues you were having?

@pillowfication
Copy link
Author

No

@jpoz-ayx
Copy link

jpoz-ayx commented Aug 22, 2023

You can pass various arguments to the FileBrowse event:

browseType: 'File' or 'Folder' (defaults to 'File')
fileTypeFilters: File type filter string
For example: Workflows, Apps and Macros|*.yxmd;*.yxwz;*.yxmc;
(See https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.filedialog.filter?view=netframework-4.6#system-windows-forms-filedialog-filter)
startingDirectory: The starting directory
defaultExtensionChoice: The default extension choice
Callback: The JavaScript function to call when the file is selected

@kingedward35
Copy link
Collaborator

Hey Pillow, has this issue been resolved for you?

@pillowfication
Copy link
Author

pillowfication commented Sep 15, 2023

I managed to find some more parameters and types through some trial-and-error for anyone else searching.

import { JsEvent } from '@alteryx/react-comms'

export type AyxDataType = 'String' | 'WString' | 'V_String' | 'V_WString' | 'Byte' | 'Int16' | 'Int32' | 'Int64' | 'Fixed Decimal' | 'Float' | 'Double' | 'Date' | 'Time' | 'DateTime' | 'Bool' | 'SpatialObj'
export type AyxEncryptionMode: 'obfuscation' | 'machine' | 'user'

export type AyxModel<
  AyxConfiguration extends Record<string, any>,
  AyxSecrets extends Record<string, { text: string, encryptionMode: AyxEncryptionMode }>
> = {
  Annotation: string | undefined
  Configuration: AyxConfiguration
  Meta: unknown
  Secrets: AyxSecrets
  ToolId: number
  ToolName: string
  srcData: unknown
}

const createDispatcher = <I, O> (jsEvent: string): (options: I) => Promise<O> =>
  async (options: I) => await (JsEvent(jsEvent, options as any) as Promise<O>)

/**
 * "SaveExpression" - Add an expression to the list of saved expressions.
 */
export const SaveExpression = createDispatcher<{
  name: string
  expression: string
}, undefined>('SaveExpression')

/**
 * "SetConfiguration" - Inform Designer that the configuration is set.
 *
 * Warning: Designer will begin to process the configuration, but the promise will not resolve.
 */
export const SetConfiguration = createDispatcher<null, never>('SetConfiguration')

/**
 * "GetConfiguration" - Inform Designer to get the configuration.
 *
 * Warning: The configuration will be saved, but the promise will not resolve.
 */
export const GetConfiguration = createDispatcher<{
  Configuration: AyxModel<Record<string, any>, Record<string, any>>
}, never>('GetConfiguration')

/**
 * "RequestConfiguration" - Gets the entire configuration for the tool. The return value is a JSON string that implements the `RequestConfigurationResult` interface.
 */
export const RequestConfiguration = createDispatcher<null, string>('RequestConfiguration')
export interface RequestConfigurationResult {
  Configuration: {
    Configuration: Record<string, any>
  }
  Fields: unknown | null
  ImageBorders: unknown | null
  IsFirstConfig: boolean
  IsForAlteryxBetaTesting: boolean
  IsLoaded: unknown | null
  IsNoConfig: boolean
  MacroMode: boolean
  MetaInfo: Array<{
    MetaInfo: {
      '@connection': string
      RecordInfo: {
        Field: Array<{
          '@name': string
          '@size'?: string
          '@type': AyxDataType
        }>
      }
    }
  }>
  NumIncomingConnections: 0
  Snippets: Record<any, unknown>
  Thumbnails: unknown | null
  ToolId: number
  ToolName: string
  VisFolderPath: unknown | null
}

/**
 * "GetInputData" - Get data from any input connections.
 */
export const GetInputData = createDispatcher<{
  anchorIndex: number
  connectionName: string
  numRecs?: number
  offset?: number
}, {
  fields: Array<{
    strName: string
    strType: AyxDataType
    nSize: string
    strSource: string
    strDescription: string
  }>
  numRecs: number
  data: string[][]
} | {
  errorCode: number
  errorMsg: string
}>('GetInputData')

/**
 * "Encrypt" - Encrypt a string.
 */
export const Encrypt = createDispatcher<{
  text: string
  encryptionMode?: AyxEncryptionMode
}, string>('Encrypt')

/**
 * "Decrypt" - Decrypt a string.
 */
export const Decrypt = createDispatcher<{
  text: string
  encryptionMode?: AyxEncryptionMode
}, string>('Decrypt')

/**
 * "TestExpression" - Parse and test if an expression is valid.
 */
export const TestExpression = createDispatcher<{
  expression: string
  customFields: Array<{
    name: string
    type: AyxDataType
  }>
}, {
  error: {
    errorMessage: string
    charPosition: number
  }
  syntaxObj: string
}>('TestExpression')

/**
 * "FormulaPreview"
 */
export const FormulaPreview = createDispatcher<unknown, unknown>('FormulaPreview')

/**
 * "FileBrowse" - Open a file explorer window and get the path of the selected file or directory.
 */
export const FileBrowse = createDispatcher<{
  browseType?: 'File' | 'Folder'
  startingDirectory?: string
  fileTypeFilters?: string
  defaultExtensionChoice?: unknown
}, string>('FileBrowse')

/**
 * "GetFormulaConstants" - Get a list of all formula constants and question constants.
 */
export const GetFormulaConstants = createDispatcher<null, {
  formulaConstants: Array<{
    Namespace: string
    Name: string
    Value: string
    IsNumeric: boolean
    FullName: string
  }>
  questionConstants: unknown[]
}>('GetFormulaConstants')

/**
 * "GetFormulaRecentAndSavedExpressions" - Get a list of all recent expressions and saved expressions.
 */
export const GetFormulaRecentAndSavedExpressions = createDispatcher<null, {
  recentExpressions: Array<{
    name: string
    expression: string
  }>
  savedExpressions: Array<{
    name: string
    expression: string
  }>
}>('GetFormulaRecentAndSavedExpressions')

/**
 * "SaveFormulaRecentExpression" - Add an expression to the list of recent expressions.
 *
 * Warning: The formula will be added, but the promise will not resolve.
 */
export const SaveFormulaRecentExpression = createDispatcher<{
  expressionText: string
}, never>('SaveFormulaRecentExpression')

/**
 * "RenameSavedExpression" - Rename a saved expression.
 */
export const RenameSavedExpression = createDispatcher<{
  oldName: string
  newName: string
}, undefined>('RenameSavedExpression')

/**
 * "DeleteSavedExpression" - Delete a saved expression.
 */
export const DeleteSavedExpression = createDispatcher<{
  expressionName: string
}, undefined>('DeleteSavedExpression')

/**
 * "OpenHelpPage" - Opens https://help.alteryx.com/current/.
 */
export const OpenHelpPage = createDispatcher<null, undefined>('OpenHelpPage')

/**
 * "ConfigureVisualLayout"
 */
export const ConfigureVisualLayout = createDispatcher<unknown, unknown>('ConfigureVisualLayout')

/**
 * "ConfigureCharting"
 */
export const ConfigureCharting = createDispatcher<unknown, unknown>('ConfigureCharting')

/**
 * "GenerateFormulaExpressions" - Get a list of all functions, operators, and conditionals.
 */
export const GenerateFormulaExpressions = createDispatcher<null, {
  FUNCTIONS: Array<{
    category: string
    description: string
    name: string
    parameters: string
  }>
  OPERATORS: Array<{
    category: string
    description: string
    name: string
    parameters: string
  }>
  CONDITIONALS: Array<{
    category: string
    description: string
    name: string
    parameters: string
  }>
}>('GenerateFormulaExpressions')

/**
 * "ConfigureInsight"
 */
export const ConfigureInsight = createDispatcher<unknown, unknown>('ConfigureInsight')

/**
 * "OpenAddPromoteDialog" - Open the Add Connection > Alteryx Promote URL dialog.
 */
export const OpenAddPromoteDialog = createDispatcher<null, unknown>('OpenAddPromoteDialog')

/**
 * "GetPromoteCredentialsList"
 */
export const GetPromoteCredentialsList = createDispatcher<unknown, unknown[]>('GetPromoteCredentialsList')

/**
 * "DeletePromoteCredentialsPrompt"
 */
export const DeletePromoteCredentialsPrompt = createDispatcher<unknown, unknown>('DeletePromoteCredentialsPrompt')

/**
 * "GetLockinConnectionStringKeyValue"
 */
export const GetLockinConnectionStringKeyValue = createDispatcher<unknown, unknown>('GetLockinConnectionStringKeyValue')

/**
 * "ShowInDbConnectionContextMenu"
 */
export const ShowInDbConnectionContextMenu = createDispatcher<unknown, unknown>('ShowInDbConnectionContextMenu')

/**
 * "GetFileContents" - Get the contents of a file.
 */
export const GetFileContents = createDispatcher<{
  Path: string
}, string>('GetFileContents')

/**
 * "ConvertJupyter"
 */
export const ConvertJupyter = createDispatcher<unknown, string>('ConvertJupyter')

/**
 * "GenerateSimpleFormulaExpression"
 */
export const GenerateSimpleFormulaExpression = createDispatcher<unknown, unknown | {
  invalid: boolean
}>('GenerateSimpleFormulaExpression')

/**
 * "AddTableauAlias"
 */
export const AddTableauAlias = createDispatcher<unknown, unknown>('AddTableauAlias')

/**
 * "GetAllTableauAliases"
 */
export const GetAllTableauAliases = createDispatcher<unknown, unknown[]>('GetAllTableauAliases')

/**
 * "GetTableauAlias"
 */
export const GetTableauAlias = createDispatcher<unknown, unknown>('GetTableauAlias')

/**
 * "DeleteTableauAlias"
 */
export const DeleteTableauAlias = createDispatcher<unknown, unknown>('DeleteTableauAlias')

/**
 * "DeleteAllTableauAliases"
 */
export const DeleteAllTableauAliases = createDispatcher<unknown, unknown>('DeleteAllTableauAliases')

/**
 * "GetSparkConnectionType"
 */
export const GetSparkConnectionType = createDispatcher<unknown, unknown>('GetSparkConnectionType')

/**
 * "GetRecentColors"
 */
export const GetRecentColors = createDispatcher<unknown, unknown[]>('GetRecentColors')

/**
 * "SaveRecentColor"
 */
export const SaveRecentColor = createDispatcher<unknown, unknown[]>('SaveRecentColor')

/**
 * "GetAlteryxTempDir" - Gets the temp directory (e.g. C:\Users\{username}\AppData\Local\Temp\).
 */
export const GetAlteryxTempDir = createDispatcher<null, string>('GetAlteryxTempDir')

/**
 * "NewCallBack"
 */
export const NewCallBack = createDispatcher<unknown, unknown>('NewCallBack')

/**
 * "InsightDataExists" - Gets if insight data exists.
 */
export const InsightDataExists = createDispatcher<null, boolean>('InsightDataExists')

/**
 * "MD5Hash" - Gets the MD5 hash of a string.
 */
export const MD5Hash = createDispatcher<{
  value: string
}, string>('MD5Hash')

/**
 * "OpenAyxModelModal"
 */
export const OpenAyxModelModal = createDispatcher<unknown, unknown>('OpenAyxModelModal')

/**
 * "AddToolsToCanvas"
 */
export const AddToolsToCanvas = createDispatcher<unknown, unknown>('AddToolsToCanvas')

/**
 * "CheckFileExits" - Check if a file exists.
 */
export const CheckFileExits = createDispatcher<unknown, boolean>('CheckFileExits')

/**
 * "CheckIfFeatureIsLicensed" - Check if a feature is licensed.
 */
export const CheckIfFeatureIsLicensed = createDispatcher<unknown, {
  featureIsActive: boolean
  featureIsInstalled: boolean
}>('CheckIfFeatureIsLicensed')

/**
 * "SaveDataToFile" - Opens a file explorer window and saves data to the specified file.
 */
export const SaveDataToFile = createDispatcher<unknown, never>('SaveDataToFile')

/**
 * "GetGoogleAuth"
 */
export const GetGoogleAuth = createDispatcher<unknown, unknown>('GetGoogleAuth')

/**
 * "GetAzureOAuth"
 */
export const GetAzureOAuth = createDispatcher<unknown, unknown | {
  error_code: string
  error_message: string
}>('GetAzureOAuth')

/**
 * "GetRefreshAzureOAuth"
 */
export const GetRefreshAzureOAuth = createDispatcher<unknown, unknown | {
  error_code: string
  error_message: string
}>('GetRefreshAzureOAuth')

/**
 * "GetSortOptions"
 */
export const GetSortOptions = createDispatcher<null, {
  defaultValue: string
  options: Record<string, string>
}>('GetSortOptions')

/**
 * "DeleteCookie"
 *
 * Warning: This seems to crash Designer.
 */
export const DeleteCookie = createDispatcher<unknown, unknown>('DeleteCookie')

/**
 * "SetupConnection"
 */
export const SetupConnection = createDispatcher<{
  body: unknown
}, {
  status: number
  body: {
    errorCode: number
    message: string
    type: string
  }
}>('SetupConnection')

/**
 * "DcmRestCall"
 */
export const DcmRestCall = createDispatcher<unknown, {
  status: number
  body: {
    message: string
    errorCode: number
    detail: string
  }
}>('DcmRestCall')

/**
 * "GetGenericOAuth"
 */
export const GetGenericOAuth = createDispatcher<{
  body: unknown
}, {
  status: number
  body: {
    errorCode: number
    message: string
    type: string
  }
}>('GetGenericOAuth')

/**
 * "MakeWebRequest"
 */
export const MakeWebRequest = createDispatcher<{
  body: unknown
}, {
  status: number
  body: {
    errorCode: number
    message: string
    type: string
  }
}>('MakeWebRequest')

/**
 * "RedeemAuthorizationCode"
 */
export const RedeemAuthorizationCode = createDispatcher<{
  body: unknown
}, {
  status: number
  body: {
    errorCode: number
    message: string
    type: string
  }
}>('RedeemAuthorizationCode')

/**
 * "OpenUserSettings"
 */
export const OpenUserSettings = createDispatcher<{
  body: unknown
}, {
  status: number
  body: {
    errorCode: number
    message: string
    type: string
  }
}>('OpenUserSettings')

/**
 * "GetFeatureToggle"
 */
export const GetFeatureToggle = createDispatcher<{
  body: unknown
}, {
  status: number
  body: {
    errorCode: number
    message: string
    type: string
  }
}>('GetFeatureToggle')

@kingedward35
Copy link
Collaborator

Hey Pillow. Thanks for the update and the information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants