Here you can enter the code that needs to run when this trigger occurs. 
The action can manipulate rows in the database, manipulate files, interact 
with remote APIs, or issue directives for the user's display.

Your code can use await at the top level, and should do so whenever calling 
database queries or other aynchronous code (see example below)

The variable `table` is the associated table (if any; note lowercase). If you want to access a different table,
use the `Table` variable (note uppercase) to access the Table class of tables (see 
[documentation for Table class](/admin/jsdoc/classes/_saltcorn_data.models_table.Table.html))

Example:

```
await table.insertRow({name: "Alex", age: 43})
const otherTable = Table.findOne({name: "Orders"})
await otherTable.deleteRows({id: order})
```

In addition to `table` and `Table`, you can use other functions/variables:

#### `console`

Use this to print to the terminal.

Example: `console.log("Hello world")`

#### `Actions`

Use `Actions.{ACTION NAME}` to run an action.

Your available action names are: {{ Object.keys(scState.actions).join(", ") }}

Example: 

```
await Actions.set_user_language({language: "fr"})
```

#### `sleep`

A small utility function to sleep for certain number of milliseconds. Use this with await

Example: `await sleep(1000)`

#### `require`

Use require to access NPM packages listed under your [Development settings](/admin/dev)

Example: `const _ = require("underscore")`

#### `fetch` and `fetchJSON`

Use these to make HTTP API calls. `fetch` is the standard JavaScript `fetch` (provided by 
[node-fetch](https://www.npmjs.com/package/node-fetch#common-usage)). `fetchJSON` performs a fetch 
and then reads its reponse to JSON

Example: 

```
const response = await fetch('https://api.github.com/users/github');
const data = await response.json();
```

which is the same as

```
const data = await fetchJSON('https://api.github.com/users/github');
```

## Return directives

Your code can with its return value give directives to the current page. 
Valid return values are:

#### `notify`

Send a pop-up notification indicating success to the user

You can additionally set in the object:
* remove_delay: seconds before remove
* notify_type: `"info"`, `"warning"`, `"danger"`, `"success"`
* toast_title: the popup title string

Example: 

```
return { 
  notify: "Order completed!", 
  notify_type: "warning", 
  remove_delay: 5
}
```

#### `error`

Send a pop-up notification indicating error to the user.

Example: `return { error: "Invalid command!" }`

If this is triggered by an Edit view with the SubmitWithAjax, 
halt navigation and stay on page. This can be used for complex validation logic, 
when added as a Validate trigger. 

#### `goto`

Navigate to a different URL: 

Example: `return { goto: "https://saltcorn.com" }`

Add `target: "_blank"` to open in a new tab.

#### `reload_page`

Request a page reload with the existing URL.

Example: `return { reload_page: true }`

#### `popup`

Open a URL in a popup: 

Example: 

```
return { popup: `/view/Orders?id=${parent}` }
```

#### `download`

Download a file to the client browser.

Example:

```
return { download: {
    mimetype: "text/csv",
    filename: "stock.csv",
    blob: filecontents
  }
}
```

#### `set_fields`

If triggered from an edit view, set fields dynamically in the form. The 
value should be an object with keys that are field variable names.

Example:

```
return { set_fields: {
    zidentifier: `${name.toUpperCase()}-${id}`
  }
}
```

#### `eval_js`

Execute JavaScript in the browser.

Example: `return { eval_js: 'alert("Hello world")' }`

#### `reload_embedded_view`

Reload the embedded view by name. Optionally, also give a new state (as a string in query string format) with the `new_state` key.

Examples:

```
return { reload_embedded_view: "booklist"}
```

with new state

```
return { reload_embedded_view: "booklist", new_state: "publisher=5&category=Romance"}
```

#### `progress_bar_update`

Creates or updates a progress bar. The value for `progress_bar_update` must be an object with the following keys:

* `blocking`: true if this a popup modal which blocks the UI. Must specify `blocking` or `id`
* `id`: A valid JavaScript identifier, for creating/updating a toast progress bar. Must specify `blocking` or `id`
* `close`: true if this progress bar is finished and should close
* `title`: The title of the progress bar
* `message`: The progress message
* `percent`: 0-100, set the progress bar value
* `maxHeight`: Only if blocking=true. Messages will be pushed to scrolling container with this height
* `popupWidth`: Only if blocking=true. Set the width of the popup.


Examples:

```
return { 
  progress_bar_update: {
    blocking: true,
    message: "Cloning messenger RNA",
    title: "Cell synthesis",
    percent: 45,
    maxHeight: 120,
    popupWidth: 600
  },
  page_load_tag // only display on current page; see below
}
```
### Emit Client events

Use `emit_to_client' to send socket.io events to one or multiple clients. For example, to notify the user with id 1:
```
emit_to_client({notify: "hello admin"}, 1);
```
This event goes to each tab (and window) where the user is logged in. Otherwise, you can use an array or omit the second parameter to emit to default to the originating user. All return directives from the block above can be used.

Include the constant `page_load_tag` in the object to only appear on the originating tab, for instance: `emit_to_client({notify: "Hello", page_load_tag})`.
