├── .builderrc
├── .gitignore
├── .npmignore
├── README.md
├── example
├── agentAssist.js
├── checklist.js
├── counter.js
├── customer360.js
├── flashCard.js
└── taskBoard.js
├── index.js
├── now-cli.json
├── now-ui.json
├── package.json
└── src
├── agent-assist-example
├── agent-assist-item
│ ├── agentAssistItem.js
│ ├── index.js
│ ├── styles.scss
│ └── view.js
├── agent-assist
│ ├── actionHandlers.js
│ ├── agentAssist.js
│ ├── index.js
│ ├── renderSearchResponse.js
│ ├── styles.scss
│ └── view.js
├── constants.js
└── index.js
├── checklist-example
├── constants.js
├── example-checklist-item
│ ├── actions.js
│ ├── checklist-item.js
│ ├── checklist-item.scss
│ ├── index.js
│ └── view.js
├── example-checklist
│ ├── actions.js
│ ├── checklist.js
│ ├── checklist.scss
│ ├── index.js
│ └── view.js
└── index.js
├── counter-example
├── example-counter
│ ├── counter.js
│ ├── counter.scss
│ ├── index.js
│ └── view.js
└── index.js
├── customer-360-example
├── actionHandlers.js
├── constants.js
├── customer360.js
├── getCallerData.js
├── getHttpEffect.js
├── index.js
├── styles.scss
└── view.js
├── flash-card-example
├── constants.js
├── example-card-list
│ ├── card-list.js
│ ├── card-list.scss
│ ├── index.js
│ └── view.js
├── example-flash-card
│ ├── flash-card.js
│ ├── flash-card.scss
│ ├── index.js
│ └── view.js
└── index.js
├── index.js
└── task-board-example
├── behaviors
└── dragDropBehaviors.js
├── constants.js
├── example-card
├── card.js
├── card.scss
└── index.js
├── example-lane
├── index.js
├── lane.js
├── lane.scss
└── view.js
├── example-task-board
├── actions.js
├── index.js
├── task-board.js
├── task-board.scss
└── view.js
└── index.js
/.builderrc:
--------------------------------------------------------------------------------
1 | ---
2 | archetypes:
3 | - "@servicenow/cli-archetype"
4 | - "@servicenow/cli-component-archetype"
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | .DS_Store
3 | node_modules
4 | lib
5 | dist
6 | target
7 | node
8 | node_tmp
9 | npm-debug.log
10 | *.iml
11 | *.tgz
12 | coverage
13 | .now-cli
14 | .babelrc
15 | /clover.xml
16 | /coverage-final.json
17 | /lcov-report/
18 | /lcov.info
19 | /dist/
20 | /lib/
21 | /target/
22 | package-lock.json
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *~
3 | *.iml
4 | *.tgz
5 | .*.haste_cache.*
6 | .DS_Store
7 | .idea
8 | .babelrc
9 | .eslintrc
10 | npm-debug.log
11 | !lib
12 | !dist
13 | __tests__
14 | __mocks__
15 | target
16 | coverage
17 | node_modules
18 | node
19 | node_tmp
20 | /.now-cli/
21 | /lcov-report/
22 | !/now-cli.*
23 | !/dist/
24 | !/lib/
25 | !/target/
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Component built using Now Experience UI Framework
2 | ## Setting up
3 | 1. Install Now Experience CLI globally, if not done already
4 |
5 | ```
6 | npm install --global @servicenow/cli
7 | ```
8 |
9 | 2. Open the local repo folder
10 |
11 | ```
12 | cd now-experience-component-examples
13 | ```
14 |
15 | 3. Install required dependencies
16 |
17 | ```
18 | npm install
19 | ```
20 |
21 | 4. Add your instance host address to `development.proxy.origin` in the `now-cli.json` and authenticate using `now-cli login` command.
22 |
23 | ## Run examples
24 |
25 | 1. Counter Example
26 |
27 | ```
28 | npm run start:counterExample
29 | ```
30 |
31 | 2. Checklist Example
32 |
33 | ```
34 | npm run start:checklistExample
35 | ```
36 |
37 | 3. Agent Assist Example
38 |
39 | ```
40 | npm run start:agentAssistExample
41 | ```
42 |
43 | 4. Customer 360 Example
44 |
45 | ```
46 | npm run start:customer360Example
47 | ```
48 |
49 | 5. Flash Card Example
50 |
51 | ```
52 | npm run start:flashCardExample
53 | ```
54 |
55 | 6. Task Board Example
56 |
57 | ```
58 | npm run start:taskBoardExample
59 | ```
60 |
61 | > To know more about `now-cli`, see [Now Experience CLI](https://developer.servicenow.com/dev.do#!/guide/orlando/now-experience/cli/cli)
62 |
63 | > To know more about NOW UI Framework, see [Now® Experience UI Framework](https://developer.servicenow.com/dev.do#!/guides/orlando/now-experience/ui-framework/getting-started/introduction)
64 |
--------------------------------------------------------------------------------
/example/agentAssist.js:
--------------------------------------------------------------------------------
1 | import '../src/agent-assist-example';
2 |
3 | const el = document.createElement('DIV');
4 | document.body.appendChild(el);
5 |
6 | el.innerHTML = `
7 |
8 |
9 |
10 | `;
11 |
--------------------------------------------------------------------------------
/example/checklist.js:
--------------------------------------------------------------------------------
1 | import '../src/checklist-example';
2 |
3 | const el = document.createElement('DIV');
4 | document.body.appendChild(el);
5 |
6 | el.innerHTML = `
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/example/counter.js:
--------------------------------------------------------------------------------
1 | import '../src/counter-example';
2 |
3 | const el = document.createElement('DIV');
4 | document.body.appendChild(el);
5 |
6 | el.innerHTML = `
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/example/customer360.js:
--------------------------------------------------------------------------------
1 | import '../src/customer-360-example';
2 |
3 | const el = document.createElement('DIV');
4 | document.body.appendChild(el);
5 |
6 | el.innerHTML = `
7 |
8 |
9 |
10 | `;
11 |
--------------------------------------------------------------------------------
/example/flashCard.js:
--------------------------------------------------------------------------------
1 | import '../src/flash-card-example';
2 |
3 | const el = document.createElement('DIV');
4 | document.body.appendChild(el);
5 |
6 | el.innerHTML = `
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/example/taskBoard.js:
--------------------------------------------------------------------------------
1 | import '../src/task-board-example';
2 |
3 | const el = document.createElement('DIV');
4 | document.body.appendChild(el);
5 |
6 | el.innerHTML = `
7 |
8 | `;
9 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/now-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "development": {
3 | "proxy": {
4 | "origin": "https://.com",
5 | "port": 3000,
6 | "proxies": ["/api"]
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/now-ui.json:
--------------------------------------------------------------------------------
1 | {
2 | "components": {
3 | "example-agent-assist" : {
4 | "innerComponents": [
5 | "now-icon",
6 | "now-loader",
7 | "now-heading"
8 | ]
9 | },
10 | "example-customer-360": {
11 | "innerComponents": [
12 | "now-avatar",
13 | "now-icon",
14 | "now-label-value-stacked",
15 | "now-label-value-inline",
16 | "now-heading"
17 | ],
18 | "properties": [
19 | {
20 | "name": "table",
21 | "label": "table",
22 | "description": "Name of the table to pick caller from",
23 | "readOnly": false,
24 | "fieldType": "table_name",
25 | "required": true,
26 | "defaultValue": "incident",
27 | "typeMetadata": {}
28 | },
29 | {
30 | "name": "sysId",
31 | "label": "sysId",
32 | "description": "The unique identifier for the record",
33 | "readOnly": false,
34 | "fieldType": "string",
35 | "required": true,
36 | "defaultValue": "85071a1347c12200e0ef563dbb9a71c1",
37 | "typeMetadata": {}
38 | }
39 | ]
40 | },
41 | "example-checklist" : {
42 | "uiBuilder": {
43 | "label": "Checklist",
44 | "icon": "list-fill",
45 | "description": "Logged in users can manage their tasks",
46 | "category": "primitives",
47 | "associatedTypes": [
48 | "global.core"
49 | ]
50 | },
51 | "innerComponents": [
52 | "now-heading",
53 | "now-loader",
54 | "now-button",
55 | "now-toggle",
56 | "example-checklist-item",
57 | "now-label-value-inline",
58 | "now-button-iconic"
59 | ]
60 | }
61 | },
62 | "scopeName": "x_now_components"
63 | }
64 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@servicenow/now-exeperience-sample-components",
3 | "version": "0.0.1",
4 | "private": false,
5 | "description": "Custom elements to show sample Customer360 , To-Do List & Agent Assist",
6 | "keywords": [
7 | "ServiceNow",
8 | "Now Experience UI Component",
9 | "@servicenow/now-exeperience-sample-components"
10 | ],
11 | "readme": "./README.md",
12 | "engines": {
13 | "node": ">=8.6.0",
14 | "npm": ">=5.3.0"
15 | },
16 | "module": "src/index.js",
17 | "scripts": {
18 | "start:agentAssistExample": "now-cli develop --open --entry=./agentAssist.js",
19 | "start:counterExample": "now-cli develop --open --entry=./counter.js",
20 | "start:checklistExample": "now-cli develop --open --entry=./checklist.js",
21 | "start:customer360Example": "now-cli develop --open --entry=./customer360.js",
22 | "start:flashCardExample": "now-cli develop --open --entry=./flashCard.js",
23 | "start:taskBoardExample": "now-cli develop --open --entry=./taskBoard.js"
24 | },
25 | "dependencies": {
26 | "@servicenow/behavior-rtl": "orlando",
27 | "@servicenow/now-avatar": "orlando",
28 | "@servicenow/now-heading": "orlando",
29 | "@servicenow/now-icon": "orlando",
30 | "@servicenow/now-label-value": "orlando",
31 | "@servicenow/sass-kit": "orlando",
32 | "@servicenow/sass-theme": "orlando",
33 | "@servicenow/now-loader": "orlando",
34 | "@servicenow/now-button": "orlando",
35 | "@servicenow/now-toggle": "orlando",
36 | "@servicenow/ui-core": "orlando",
37 | "@servicenow/ui-effect-http": "orlando",
38 | "@servicenow/ui-renderer-snabbdom": "orlando",
39 | "@servicenow/cli-archetype": "orlando",
40 | "@servicenow/cli-component-archetype": "orlando"
41 | },
42 | "devDependencies": {
43 | "@servicenow/cli-archetype-dev": "orlando",
44 | "@servicenow/cli-component-archetype-dev": "orlando"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist-item/agentAssistItem.js:
--------------------------------------------------------------------------------
1 | import {createCustomElement} from '@servicenow/ui-core';
2 | import snabbdom from '@servicenow/ui-renderer-snabbdom';
3 | import view from './view';
4 | import styles from './styles.scss';
5 |
6 | createCustomElement('agent-assist-item', {
7 | renderer: {type: snabbdom},
8 | view,
9 | styles,
10 | properties: {
11 | articleShortDescription: {
12 | default: null
13 | },
14 | articleBody: {
15 | default: null
16 | }
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist-item/index.js:
--------------------------------------------------------------------------------
1 | import './agentAssistItem';
2 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist-item/styles.scss:
--------------------------------------------------------------------------------
1 | @import '@servicenow/sass-kit/host';
2 |
3 | article {
4 | border-radius: $now-global-border-radius--sm;
5 | border: 1px solid RGB($now-color--divider-primary);
6 | margin: $now-global-space--sm 0px;
7 | padding: $now-global-space--md;
8 | header {
9 | display: grid;
10 | grid-template-columns: now-fn-px2rem(30px) auto;
11 | align-items: center;
12 | span {
13 | color: RGB($now-color--text-secondary);
14 | }
15 | now-heading {
16 | margin-top: $now-global-space--md;
17 | grid-column: 1 / span 2;
18 | }
19 | }
20 | summary {
21 | white-space: normal;
22 | margin-top: $now-global-space--xs;
23 | color: RGB($now-color--text-tertiary);
24 | font-size: $now-global-font-size--sm;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist-item/view.js:
--------------------------------------------------------------------------------
1 | import '@servicenow/now-heading';
2 |
3 | const trimArticleBody = function (articleBody) {
4 | if (articleBody)
5 | return articleBody
6 | .replace(/<([^>]+)>/g, '')
7 | .replace(/(\d+);/g, (match, dec) => String.fromCharCode(dec))
8 | .substring(0, 150)
9 | .trim();
10 |
11 | return null;
12 | };
13 |
14 | export default state => {
15 | const {
16 | properties: {articleShortDescription, articleBody}
17 | } = state;
18 |
19 | return (
20 |
21 |
22 |
23 | Article
24 |
28 |
29 | {`${trimArticleBody(articleBody)}...`}
30 |
31 | );
32 | };
33 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist/actionHandlers.js:
--------------------------------------------------------------------------------
1 | import {actionTypes} from '@servicenow/ui-core';
2 | import {createHttpEffect} from '@servicenow/ui-effect-http';
3 | import {
4 | KB_KNOWLEDGE_REST_URL,
5 | KB_KNOWLEDGE_FETCH_REQUESTED,
6 | KB_KNOWLEDGE_FETCH_STARTED,
7 | KB_KNOWLEDGE_FETCH_SUCCESS,
8 | KB_KNOWLEDGE_FETCH_FAILED,
9 | SEARCH_REQUESTED,
10 | KB_KNOWLEDGE_TABLE,
11 | NUMBER_OF_RECORDS_FETCH
12 | } from '../constants';
13 |
14 | const triggerSearch = (fields, {dispatch, updateState}) => {
15 | const searchString =
16 | fields && fields.short_description && fields.short_description.value
17 | ? fields.short_description.value.trim()
18 | : '';
19 |
20 | if (searchString) {
21 | dispatch(SEARCH_REQUESTED, {searchString});
22 | } else {
23 | updateState({
24 | searchString,
25 | result: []
26 | });
27 | }
28 | };
29 |
30 | export default {
31 | [actionTypes.COMPONENT_BOOTSTRAPPED]: ({
32 | dispatch,
33 | updateState,
34 | properties: {fields}
35 | }) => {
36 | triggerSearch(fields, {dispatch, updateState});
37 | },
38 | [actionTypes.COMPONENT_PROPERTY_CHANGED]: ({
39 | dispatch,
40 | updateState,
41 | action
42 | }) => {
43 | const {
44 | payload: {value: fields}
45 | } = action;
46 | triggerSearch(fields, {dispatch, updateState});
47 | },
48 | [SEARCH_REQUESTED]: ({dispatch, updateState, action}) => {
49 | const {
50 | payload: {searchString}
51 | } = action;
52 | const sysparm_query = `short_descriptionLIKE${searchString}^ORtextLIKE${searchString}`;
53 | updateState({searchString});
54 | dispatch(KB_KNOWLEDGE_FETCH_REQUESTED, {
55 | table: KB_KNOWLEDGE_TABLE,
56 | sysparm_query,
57 | sysparm_limit: NUMBER_OF_RECORDS_FETCH
58 | });
59 | },
60 | [KB_KNOWLEDGE_FETCH_REQUESTED]: createHttpEffect(KB_KNOWLEDGE_REST_URL, {
61 | pathParams: ['table'],
62 | queryParams: ['sysparm_query', 'sysparm_limit'],
63 | startActionType: KB_KNOWLEDGE_FETCH_STARTED,
64 | successActionType: KB_KNOWLEDGE_FETCH_SUCCESS,
65 | errorActionType: KB_KNOWLEDGE_FETCH_FAILED
66 | }),
67 | [KB_KNOWLEDGE_FETCH_STARTED]: ({updateState}) => {
68 | updateState({isLoading: true});
69 | },
70 | [KB_KNOWLEDGE_FETCH_SUCCESS]: ({action, updateState}) => {
71 | const {
72 | payload: {result = []}
73 | } = action;
74 | updateState({
75 | isLoading: false,
76 | result
77 | });
78 | },
79 | [KB_KNOWLEDGE_FETCH_FAILED]: ({action, updateState}) => {
80 | const {
81 | type,
82 | payload: {
83 | statusText,
84 | data: {
85 | error: {message}
86 | }
87 | }
88 | } = action;
89 | console.error(`[${type}] ${statusText}: ${message}!`); // eslint-disable-line no-console
90 | updateState({isLoading: false, result: []});
91 | }
92 | };
93 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist/agentAssist.js:
--------------------------------------------------------------------------------
1 | import {createCustomElement} from '@servicenow/ui-core';
2 | import snabbdom from '@servicenow/ui-renderer-snabbdom';
3 | import view from './view';
4 | import actionHandlers from './actionHandlers';
5 | import styles from './styles.scss';
6 |
7 | createCustomElement('example-agent-assist', {
8 | renderer: {type: snabbdom},
9 | view,
10 | styles,
11 | initialState: {
12 | searchString: null,
13 | isLoading: false,
14 | result: []
15 | },
16 | properties: {
17 | fields: {
18 | default: {
19 | short_description: {
20 | displayValue: 'email',
21 | value: 'email',
22 | visible: true
23 | }
24 | }
25 | }
26 | },
27 | actionHandlers
28 | });
29 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist/index.js:
--------------------------------------------------------------------------------
1 | import './agentAssist';
2 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist/renderSearchResponse.js:
--------------------------------------------------------------------------------
1 | import {Fragment} from '@servicenow/ui-renderer-snabbdom';
2 | import '@servicenow/now-label-value';
3 | import '../agent-assist-item';
4 | import {NO_MATCHES_FOUND, NO_MATCHES_FOUND_MESSAGE} from '../constants';
5 |
6 | export const renderSearchResponse = result => (
7 |
8 | {result.length ? (
9 | result.map(item => (
10 |
16 | ))
17 | ) : (
18 |
19 |
20 |
21 |
22 | )}
23 |
24 | );
25 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist/styles.scss:
--------------------------------------------------------------------------------
1 | @import '@servicenow/sass-kit/host';
2 |
3 | :host {
4 | display: block;
5 | height: 100%;
6 | }
7 | .now-agent-assist {
8 | display: flex;
9 | flex-direction: column;
10 | max-width: now-fn-px2rem(300px);
11 | height: inherit;
12 | margin: auto;
13 | padding: $now-global-space--lg;
14 | background-color: RGB($now-color--background-primary);
15 | header {
16 | .now-agent-assist-search-input {
17 | width: 100%;
18 | line-height: $now-global-line-height;
19 | font-size: $now-global-font-size--md;
20 | margin-bottom: $now-global-space--lg;
21 | &:focus {
22 | outline-color: RGB($now-color--category-green-3);
23 | }
24 | }
25 | }
26 | main {
27 | overflow: auto;
28 | padding: $now-global-font-size--sm 0px;
29 | .no-response-found {
30 | display: grid;
31 | justify-items: center;
32 | grid-gap: $now-global-space--sm;
33 | padding: $now-global-space--md;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/agent-assist-example/agent-assist/view.js:
--------------------------------------------------------------------------------
1 | import '@servicenow/now-icon';
2 | import '@servicenow/now-loader';
3 | import '@servicenow/now-heading';
4 | import {renderSearchResponse} from './renderSearchResponse';
5 | import {SEARCH_REQUESTED} from '../constants';
6 |
7 | export default (state, {dispatch, updateState}) => {
8 | const {isLoading, searchString, result} = state;
9 |
10 | const triggerSearch = ({target: {value}}) => {
11 | const searchValue = value.trim();
12 |
13 | if (searchValue === searchString) {
14 | return;
15 | } else if (searchValue) {
16 | dispatch(SEARCH_REQUESTED, {searchString: searchValue});
17 | } else {
18 | updateState({
19 | searchString: searchValue,
20 | result: []
21 | });
22 | }
23 | };
24 |
25 | return (
26 |
27 |
34 |
35 | {isLoading ? (
36 |
37 | ) : (
38 | renderSearchResponse(result)
39 | )}
40 |
41 |
42 | );
43 | };
44 |
--------------------------------------------------------------------------------
/src/agent-assist-example/constants.js:
--------------------------------------------------------------------------------
1 | export const KB_KNOWLEDGE_REST_URL = '/api/now/table/:table';
2 | export const SEARCH_REQUESTED = 'SEARCH_REQUESTED';
3 | export const KB_KNOWLEDGE_FETCH_REQUESTED = 'KB_KNOWLEDGE_FETCH_REQUESTED';
4 | export const KB_KNOWLEDGE_FETCH_STARTED = 'KB_KNOWLEDGE_FETCH_STARTED';
5 | export const KB_KNOWLEDGE_FETCH_SUCCESS = 'KB_KNOWLEDGE_FETCH_SUCCESS';
6 | export const KB_KNOWLEDGE_FETCH_FAILED = 'KB_KNOWLEDGE_FETCH_FAILED';
7 | export const NO_MATCHES_FOUND = 'No matches found';
8 | export const NO_MATCHES_FOUND_MESSAGE =
9 | 'Try modifying your search text or filter to find what you\'re looking for';
10 | export const KB_KNOWLEDGE_TABLE = 'kb_knowledge';
11 | export const NUMBER_OF_RECORDS_FETCH = '10';
12 |
--------------------------------------------------------------------------------
/src/agent-assist-example/index.js:
--------------------------------------------------------------------------------
1 | import './agent-assist';
2 |
--------------------------------------------------------------------------------
/src/checklist-example/constants.js:
--------------------------------------------------------------------------------
1 | export const CHECKLIST_LOAD_REQUESTED = 'CHECKLIST_LOAD_REQUESTED';
2 | export const CHECKLIST_LOAD_SUCCEEDED = 'CHECKLIST_LOAD_SUCCEEDED';
3 | export const CHECKLIST_INPUT_CHANGED = 'CHECKLIST_INPUT_CHANGED';
4 | export const CHECKLIST_ITEM_ADD = 'CHECKLIST_ITEM_ADD';
5 | export const CHECKLIST_ITEM_UPDATED = 'CHECKLIST_ITEM_UPDATED';
6 | export const CHECKLIST_UPDATED = 'CHECKLIST_UPDATED';
7 | export const TOGGLE_CLICKED = 'NOW_TOGGLE#CHECKED_SET';
8 | export const REMOVE_BTN_CLICKED = 'NOW_BUTTON_ICONIC#CLICKED';
9 | export const URL_CURRENT_USER = 'api/now/ui/user/current_user';
10 | export const URL_TASK_TABLE = '/api/now/table/vtb_task';
11 | export const URL_UPDATE_TASK = '/api/now/table/vtb_task/:id';
12 | export const FETCH_ITEM_REQUESTED = 'FETCH_ITEM_REQUESTED';
13 | export const FETCH_ITEM_SUCCEEDED = 'FETCH_ITEM_SUCCEEDED';
14 | export const FETCH_ITEM_FAILED = 'FETCH_ITEM_FAILED';
15 | export const CREATE_ITEM_REQUESTED = 'CREATE_ITEM_REQUESTED';
16 | export const CREATE_ITEM_SUCCEEDED = 'CREATE_ITEM_SUCCEEDED';
17 | export const UPDATE_ITEM_REQUESTED = 'UPDATE_ITEM_REQUESTED';
18 | export const DELETE_ITEM_REQUESTED = 'DELETE_ITEM_REQUESTED';
19 | export const CHECKLIST_LOAD_STARTED = 'CHECKLIST_LOAD_STARTED';
20 | export const ENTER_KEY_CODE = 13;
21 | export const ESC_KEY_CODE = 27;
22 | export const FILTER = {
23 | ALL: 'all',
24 | COMPLETE: 'complete',
25 | INCOMPLETE: 'incomplete'
26 | };
27 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist-item/actions.js:
--------------------------------------------------------------------------------
1 | import {TOGGLE_CLICKED, CHECKLIST_ITEM_UPDATED} from '../constants';
2 |
3 | export default {
4 | actionHandlers: {
5 | [TOGGLE_CLICKED]: {
6 | stopPropagation: true,
7 | effect: ({state, action, dispatch}) => {
8 | action.preventDefault();
9 | const {itemId} = state.properties;
10 | const {value} = action.payload;
11 | dispatch(CHECKLIST_ITEM_UPDATED, {itemId, active: value});
12 | }
13 | }
14 | }
15 | };
16 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist-item/checklist-item.js:
--------------------------------------------------------------------------------
1 | import {createCustomElement} from '@servicenow/ui-core';
2 | import snabbdom from '@servicenow/ui-renderer-snabbdom';
3 | import styles from './checklist-item.scss';
4 | import view from './view';
5 | import checklistItemAction from './actions';
6 |
7 | createCustomElement('example-checklist-item', {
8 | renderer: {type: snabbdom},
9 | view,
10 | properties: {
11 | itemId: {
12 | default: ''
13 | },
14 | label: {
15 | default: ''
16 | },
17 | active: {
18 | default: false
19 | },
20 | editing: {
21 | default: false
22 | }
23 | },
24 | styles,
25 | ...checklistItemAction
26 | });
27 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist-item/checklist-item.scss:
--------------------------------------------------------------------------------
1 | @import '@servicenow/sass-kit/host';
2 |
3 | :host {
4 | display: block;
5 | }
6 |
7 | .now-checklist-item {
8 | display: grid;
9 | align-items: center;
10 | grid-template-columns: now-fn-px2rem(120px) 1fr now-fn-px2rem(32px);
11 | border-bottom-width: 1px;
12 | border-bottom-style: solid;
13 | border-bottom-color: RGB($now-color--divider-secondary);
14 | }
15 |
16 | .now-checklist-item-cell {
17 | display: flex;
18 | padding: $now-global-space--sm;
19 |
20 | &:first-child {
21 | border-right-width: 1px;
22 | border-right-style: solid;
23 | border-right-color: RGB($now-color--divider-secondary);
24 | }
25 |
26 | &.-center {
27 | justify-content: center;
28 | }
29 | }
30 |
31 | .now-checklist-item-input {
32 | margin: 0;
33 | padding: 0;
34 | font-size: inherit;
35 | line-height: inherit;
36 | font-family: inherit;
37 | }
38 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist-item/index.js:
--------------------------------------------------------------------------------
1 | import './checklist-item';
2 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist-item/view.js:
--------------------------------------------------------------------------------
1 | import '@servicenow/now-toggle';
2 | import {
3 | CHECKLIST_ITEM_UPDATED,
4 | ENTER_KEY_CODE,
5 | ESC_KEY_CODE
6 | } from '../constants';
7 |
8 | export default (state, {dispatch, updateProperties}) => {
9 | const {
10 | properties: {itemId, label, active, editing}
11 | } = state;
12 | const setEditing = editing => updateProperties({editing});
13 |
14 | const labelCell = (
15 | setEditing(true)}>
19 | {label}
20 |
21 | );
22 |
23 | const inputCell = (
24 |
25 | vnode.elm.focus()}
29 | on-keydown={({keyCode, target: {value: label}}) => {
30 | const newLabel = label.trim();
31 | if (keyCode === ENTER_KEY_CODE) {
32 | setEditing(false);
33 | if (newLabel) {
34 | dispatch(CHECKLIST_ITEM_UPDATED, {
35 | itemId,
36 | short_description: newLabel
37 | });
38 | }
39 | } else if (keyCode === ESC_KEY_CODE) {
40 | setEditing(false);
41 | }
42 | }}
43 | on-blur={() => setEditing(false)}
44 | />
45 |
46 | );
47 |
48 | return (
49 |
50 |
51 |
52 |
53 | {editing ? inputCell : labelCell}
54 |
61 |
62 | );
63 | };
64 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist/actions.js:
--------------------------------------------------------------------------------
1 | import {actionTypes} from '@servicenow/ui-core';
2 | import {createHttpEffect} from '@servicenow/ui-effect-http';
3 | import {
4 | CHECKLIST_LOAD_SUCCEEDED,
5 | CHECKLIST_ITEM_ADD,
6 | CHECKLIST_ITEM_UPDATED,
7 | URL_CURRENT_USER,
8 | FETCH_ITEM_REQUESTED,
9 | URL_TASK_TABLE,
10 | FETCH_ITEM_SUCCEEDED,
11 | FETCH_ITEM_FAILED,
12 | CREATE_ITEM_REQUESTED,
13 | CREATE_ITEM_SUCCEEDED,
14 | URL_UPDATE_TASK,
15 | UPDATE_ITEM_REQUESTED,
16 | REMOVE_BTN_CLICKED,
17 | DELETE_ITEM_REQUESTED,
18 | CHECKLIST_LOAD_STARTED,
19 | CHECKLIST_LOAD_REQUESTED
20 | } from '../constants';
21 |
22 | export default {
23 | actionHandlers: {
24 | [actionTypes.COMPONENT_BOOTSTRAPPED]: ({dispatch}) => {
25 | dispatch(CHECKLIST_LOAD_REQUESTED);
26 | },
27 | [CHECKLIST_LOAD_REQUESTED]: createHttpEffect(URL_CURRENT_USER, {
28 | startActionType: CHECKLIST_LOAD_STARTED,
29 | successActionType: CHECKLIST_LOAD_SUCCEEDED
30 | }),
31 | [CHECKLIST_LOAD_STARTED]: ({updateState}) => {
32 | updateState({isLoading: true});
33 | },
34 | [CHECKLIST_LOAD_SUCCEEDED]: ({
35 | action: {
36 | payload: {result = {}}
37 | },
38 | dispatch,
39 | updateState
40 | }) => {
41 | const {user_sys_id: userSysId} = result;
42 | if (userSysId) {
43 | updateState({userSysId});
44 | dispatch(FETCH_ITEM_REQUESTED, {
45 | sysparm_fields: 'sys_id,short_description,active,assigned_to',
46 | sysparm_query: `assigned_to=${userSysId}^ORDERBYDESCsys_created_on`
47 | });
48 | } else {
49 | updateState({isLoading: false});
50 | }
51 | },
52 | [FETCH_ITEM_REQUESTED]: createHttpEffect(URL_TASK_TABLE, {
53 | queryParams: ['sysparm_fields', 'sysparm_query'],
54 | errorActionType: FETCH_ITEM_FAILED,
55 | successActionType: FETCH_ITEM_SUCCEEDED
56 | }),
57 | [FETCH_ITEM_SUCCEEDED]: ({action, updateState}) => {
58 | const {
59 | payload: {result = []}
60 | } = action;
61 | updateState({isLoading: false});
62 | updateState({
63 | path: 'items',
64 | operation: 'concat',
65 | value: result.map(item => ({
66 | short_description: item.short_description,
67 | active: item.active === 'true',
68 | itemId: item.sys_id
69 | }))
70 | });
71 | },
72 | [CHECKLIST_ITEM_ADD]: ({action, updateState, dispatch, state}) => {
73 | const {
74 | payload: {inputValue}
75 | } = action;
76 | const {userSysId} = state;
77 | updateState({inputValue: ''});
78 | dispatch(CREATE_ITEM_REQUESTED, {
79 | data: {
80 | short_description: inputValue,
81 | assigned_to: userSysId,
82 | active: false
83 | }
84 | });
85 | },
86 | [CREATE_ITEM_REQUESTED]: createHttpEffect(URL_TASK_TABLE, {
87 | method: 'POST',
88 | dataParam: 'data',
89 | successActionType: CREATE_ITEM_SUCCEEDED
90 | }),
91 | [CREATE_ITEM_SUCCEEDED]: ({action, updateState}) => {
92 | const {
93 | payload: {result}
94 | } = action;
95 | updateState({
96 | path: 'items',
97 | operation: 'unshift',
98 | value: {
99 | short_description: result.short_description,
100 | active: result.active === 'true',
101 | itemId: result.sys_id
102 | }
103 | });
104 | },
105 | [CHECKLIST_ITEM_UPDATED]: ({action, updateState, state, dispatch}) => {
106 | const {payload} = action;
107 | updateState({
108 | items: state.items.map(item =>
109 | item.itemId === payload.itemId
110 | ? {
111 | ...item,
112 | ...action.payload
113 | }
114 | : {...item}
115 | )
116 | });
117 | dispatch(UPDATE_ITEM_REQUESTED, {
118 | data: {...payload},
119 | id: payload.itemId
120 | });
121 | },
122 | [UPDATE_ITEM_REQUESTED]: createHttpEffect(URL_UPDATE_TASK, {
123 | method: 'PUT',
124 | dataParam: 'data',
125 | pathParams: ['id']
126 | }),
127 | [REMOVE_BTN_CLICKED]: ({action, updateState, dispatch, state}) => {
128 | const {
129 | payload: {itemId}
130 | } = action;
131 | updateState({
132 | items: state.items.filter(item => item.itemId !== itemId)
133 | });
134 | dispatch(DELETE_ITEM_REQUESTED, {id: itemId});
135 | },
136 | [DELETE_ITEM_REQUESTED]: createHttpEffect(URL_UPDATE_TASK, {
137 | method: 'DELETE',
138 | pathParams: ['id']
139 | })
140 | }
141 | };
142 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist/checklist.js:
--------------------------------------------------------------------------------
1 | import {createCustomElement} from '@servicenow/ui-core';
2 | import snabbdom from '@servicenow/ui-renderer-snabbdom';
3 | import view from './view';
4 | import styles from './checklist.scss';
5 | import checklistActions from './actions';
6 | import rtlBehavior from '@servicenow/behavior-rtl';
7 | import {FILTER} from '../constants';
8 |
9 | createCustomElement('example-checklist', {
10 | renderer: {type: snabbdom},
11 | view,
12 | initialState: {
13 | inputValue: '',
14 | userSysId: '',
15 | items: [],
16 | isLoading: false
17 | },
18 | properties: {
19 | itemsLeft: {
20 | computed({items = []}) {
21 | return items.filter(item => !item.active).length;
22 | }
23 | },
24 | filter: {
25 | default: FILTER.ALL
26 | }
27 | },
28 | ...checklistActions,
29 | styles,
30 | behaviors: [rtlBehavior]
31 | });
32 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist/checklist.scss:
--------------------------------------------------------------------------------
1 | @import '@servicenow/sass-kit/host';
2 |
3 | :host {
4 | display: block;
5 | }
6 |
7 | .now-checklist {
8 | max-width: now-fn-px2rem(800px);
9 | margin: $now-global-space--md auto;
10 | padding: $now-global-space--xxl;
11 | box-shadow: $now-global-drop-shadow--md;
12 | background-color: RGB($now-color--background-primary);
13 | now-loader {
14 | margin-top: $now-global-space--md;
15 | }
16 | }
17 |
18 | .now-checklist-input {
19 | display: block;
20 | width: 100%;
21 | margin-bottom: $now-global-space--lg;
22 | padding: $now-global-space--md;
23 | font-size: $now-global-font-size--lg;
24 | font-family: inherit;
25 | }
26 |
27 | .now-checklist-thead {
28 | display: grid;
29 | grid-template-columns: now-fn-px2rem(120px) 1fr;
30 | border-bottom-width: 1px;
31 | border-bottom-style: solid;
32 | border-bottom-color: RGB($now-color--divider-secondary);
33 | }
34 |
35 | .now-checklist-th {
36 | padding-right: $now-global-space--sm;
37 | padding-bottom: $now-global-space--sm;
38 | padding-left: $now-global-space--sm;
39 | font-weight: bold;
40 |
41 | &.-center {
42 | text-align: center;
43 | }
44 | }
45 |
46 | .now-checklist-footer {
47 | display: flex;
48 | align-items: center;
49 | }
50 |
51 | .now-checklist-button {
52 | @include now-mx-rtl-property(margin-left, auto);
53 | }
54 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist/index.js:
--------------------------------------------------------------------------------
1 | import './checklist';
2 |
--------------------------------------------------------------------------------
/src/checklist-example/example-checklist/view.js:
--------------------------------------------------------------------------------
1 | import '@servicenow/now-heading';
2 | import '@servicenow/now-button';
3 | import '@servicenow/now-loader';
4 | import '@servicenow/now-label-value';
5 | import '../example-checklist-item';
6 | import {CHECKLIST_ITEM_ADD, ENTER_KEY_CODE, FILTER} from '../constants';
7 |
8 | const filterItems = (items, filter) => {
9 | switch (filter) {
10 | case FILTER.ALL:
11 | return items;
12 | case FILTER.INCOMPLETE:
13 | return items.filter(item => !item.active);
14 | case FILTER.COMPLETE:
15 | return items.filter(item => item.active);
16 | }
17 | };
18 |
19 | export default (state, {dispatch, updateProperties}) => {
20 | const {
21 | properties: {itemsLeft, filter},
22 | items,
23 | inputValue,
24 | isLoading
25 | } = state;
26 | const filteredItems = filterItems(items, filter);
27 | return (
28 |
29 |
32 | {
38 | const inputValue = value.trim();
39 | if (keyCode === ENTER_KEY_CODE && inputValue) {
40 | dispatch(CHECKLIST_ITEM_ADD, {inputValue});
41 | }
42 | }}
43 | />
44 |
45 |
46 |
47 |
48 | Mark as done
49 |
50 |
51 | Task
52 |
53 |
54 |
55 |
56 | {isLoading ? (
57 |
58 | ) : (
59 | filteredItems.map(item => (
60 |
66 | ))
67 | )}
68 | {!filteredItems.length ? (
69 |
70 | ) : null}
71 |
72 |
73 |
101 |
102 | );
103 | };
104 |
--------------------------------------------------------------------------------
/src/checklist-example/index.js:
--------------------------------------------------------------------------------
1 | import './example-checklist';
2 |
--------------------------------------------------------------------------------
/src/counter-example/example-counter/counter.js:
--------------------------------------------------------------------------------
1 | import {createCustomElement} from '@servicenow/ui-core';
2 | import snabbdom from '@servicenow/ui-renderer-snabbdom';
3 | import style from './counter.scss';
4 | import view from './view';
5 |
6 | createCustomElement('example-counter', {
7 | renderer: {type: snabbdom},
8 | view,
9 | initialState: {
10 | tally: 0
11 | },
12 | styles: style
13 | });
14 |
--------------------------------------------------------------------------------
/src/counter-example/example-counter/counter.scss:
--------------------------------------------------------------------------------
1 | .counter {
2 | margin: 15px;
3 | }
4 |
5 | h2 {
6 | font-family: Arial;
7 | color: seagreen;
8 | }
9 |
10 | button {
11 | margin: 4px;
12 | padding: 8px;
13 | border: 1px solid darkgray;
14 | }
15 |
16 | h3 {
17 | align-content: center;
18 | font-size: 16px;
19 | margin: 12px;
20 | }
21 |
--------------------------------------------------------------------------------
/src/counter-example/example-counter/index.js:
--------------------------------------------------------------------------------
1 | import './counter.js';
2 |
--------------------------------------------------------------------------------
/src/counter-example/example-counter/view.js:
--------------------------------------------------------------------------------
1 | export default (state, {updateState}) => {
2 | const {tally} = state;
3 | return (
4 |
5 |
Click Counter
6 |
7 |
12 |
13 |
14 |
17 |
18 |
Value: {tally}
19 |
20 | );
21 | };
22 |
--------------------------------------------------------------------------------
/src/counter-example/index.js:
--------------------------------------------------------------------------------
1 | import './example-counter';
2 |
--------------------------------------------------------------------------------
/src/customer-360-example/actionHandlers.js:
--------------------------------------------------------------------------------
1 | import {actionTypes} from '@servicenow/ui-core';
2 | import {getHttpEffect} from './getHttpEffect';
3 | import {
4 | INCIDENT_FETCH_REQUESTED,
5 | INCIDENT_FETCH_SUCCEEDED,
6 | INCIDENT_FETCH_FAILED,
7 | USER_FETCH_REQUESTED,
8 | USER_FETCH_SUCCEEDED,
9 | USER_FETCH_FAILED,
10 | INCIDENT_TABLE,
11 | FETCH_COMPANY,
12 | FETCH_LOCATION,
13 | COMPANY_FETCH_SUCCEEDED,
14 | LOCATION_FETCH_SUCCEEDED,
15 | LOCATION_TABLE,
16 | COMPANY_TABLE,
17 | USER_TABLE,
18 | OPEN_USER_DETAILS,
19 | PREVIEW_RECORD
20 | } from './constants';
21 |
22 | export default {
23 | [actionTypes.COMPONENT_BOOTSTRAPPED]: ({
24 | dispatch,
25 | updateState,
26 | properties
27 | }) => {
28 | const {table, sysid} = properties;
29 |
30 | if (table === INCIDENT_TABLE && sysid) {
31 | updateState({isLoading: true});
32 | dispatch(INCIDENT_FETCH_REQUESTED, {sysId: sysid, table});
33 | }
34 | },
35 | [INCIDENT_FETCH_REQUESTED]: getHttpEffect({
36 | successActionType: INCIDENT_FETCH_SUCCEEDED,
37 | errorActionType: INCIDENT_FETCH_FAILED
38 | }),
39 | [INCIDENT_FETCH_SUCCEEDED]: ({dispatch, action, updateState}) => {
40 | const {
41 | payload: {result}
42 | } = action;
43 |
44 | if (result && result.caller_id && result.caller_id.value) {
45 | dispatch(USER_FETCH_REQUESTED, {
46 | sysId: result.caller_id.value,
47 | table: USER_TABLE
48 | });
49 | } else {
50 | updateState({isLoading: false});
51 | }
52 | },
53 | [USER_FETCH_REQUESTED]: getHttpEffect({
54 | successActionType: USER_FETCH_SUCCEEDED,
55 | errorActionType: USER_FETCH_FAILED
56 | }),
57 | [USER_FETCH_SUCCEEDED]: ({action, dispatch, updateState}) => {
58 | const {
59 | payload: {result}
60 | } = action;
61 |
62 | if (!result) {
63 | updateState({isLoading: false});
64 | } else {
65 | const location = result.location && result.location.value;
66 | if (location)
67 | dispatch(FETCH_LOCATION, {sysId: location, table: LOCATION_TABLE});
68 |
69 | const company = result.company && result.company.value;
70 | if (company)
71 | dispatch(FETCH_COMPANY, {sysId: company, table: COMPANY_TABLE});
72 |
73 | updateState({
74 | userResult: result,
75 | isLoading: false
76 | });
77 | }
78 | },
79 | [FETCH_LOCATION]: getHttpEffect({
80 | successActionType: LOCATION_FETCH_SUCCEEDED
81 | }),
82 | [FETCH_COMPANY]: getHttpEffect({
83 | successActionType: COMPANY_FETCH_SUCCEEDED
84 | }),
85 | [COMPANY_FETCH_SUCCEEDED]: ({updateState, action}) => {
86 | const {
87 | payload: {result}
88 | } = action;
89 |
90 | if (result) updateState({companyResult: result});
91 | },
92 | [LOCATION_FETCH_SUCCEEDED]: ({updateState, action}) => {
93 | const {
94 | payload: {result}
95 | } = action;
96 |
97 | if (result) updateState({locationResult: result});
98 | },
99 | [INCIDENT_FETCH_FAILED]: ({updateState}) => updateState({isLoading: false}),
100 | [USER_FETCH_FAILED]: ({updateState}) => updateState({isLoading: false}),
101 | [OPEN_USER_DETAILS]: ({state, dispatch}) => {
102 | const {
103 | userResult: {sys_id}
104 | } = state;
105 |
106 | dispatch(PREVIEW_RECORD, {
107 | table: USER_TABLE,
108 | sys_id
109 | });
110 | }
111 | };
112 |
--------------------------------------------------------------------------------
/src/customer-360-example/constants.js:
--------------------------------------------------------------------------------
1 | export const INCIDENT_FETCH_REQUESTED = 'INCIDENT_FETCH_REQUESTED';
2 | export const INCIDENT_FETCH_SUCCEEDED = 'INCIDENT_FETCH_SUCCEEDED';
3 | export const INCIDENT_FETCH_FAILED = 'INCIDENT_FETCH_FAILED';
4 | export const USER_FETCH_REQUESTED = 'USER_FETCH_REQUESTED';
5 | export const USER_FETCH_SUCCEEDED = 'USER_FETCH_SUCCEEDED';
6 | export const USER_FETCH_FAILED = 'USER_FETCH_FAILED';
7 | export const LOCATION_FETCH_SUCCEEDED = 'LOCATION_FETCH_SUCCEEDED';
8 | export const COMPANY_FETCH_SUCCEEDED = 'COMPANY_FETCH_SUCCEEDED';
9 | export const FETCH_LOCATION = 'FETCH_LOCATION';
10 | export const FETCH_COMPANY = 'FETCH_COMPANY';
11 | export const INCIDENT_TABLE = 'incident';
12 | export const COMPANY_TABLE = 'core_company';
13 | export const LOCATION_TABLE = 'cmn_location';
14 | export const USER_TABLE = 'sys_user';
15 | export const NO_DATA = 'No Data';
16 | export const PREVIEW_RECORD = 'PREVIEW_RECORD';
17 | export const OPEN_USER_DETAILS = 'OPEN_USER_DETAILS';
18 |
--------------------------------------------------------------------------------
/src/customer-360-example/customer360.js:
--------------------------------------------------------------------------------
1 | import {createCustomElement} from '@servicenow/ui-core';
2 | import snabbdom from '@servicenow/ui-renderer-snabbdom';
3 | import '@servicenow/now-avatar';
4 | import '@servicenow/now-label-value';
5 | import styles from './styles.scss';
6 | import view from './view';
7 | import actionHandlers from './actionHandlers';
8 |
9 | createCustomElement('example-customer-360', {
10 | renderer: {type: snabbdom},
11 | view,
12 | initialState: {
13 | userResult: {},
14 | isLoading: true,
15 | locationResult: {},
16 | companyResult: {}
17 | },
18 | properties: {
19 | table: {
20 | default: ''
21 | },
22 | sysid: {
23 | default: ''
24 | }
25 | },
26 | styles,
27 | actionHandlers
28 | });
29 |
--------------------------------------------------------------------------------
/src/customer-360-example/getCallerData.js:
--------------------------------------------------------------------------------
1 | import {NO_DATA} from './constants';
2 |
3 | export default function getCallerData(
4 | userResult,
5 | locationResult,
6 | companyResult
7 | ) {
8 | const {name, photo} = userResult;
9 | const itemOne = [
10 | {label: 'Name', value: {type: 'string', value: name}},
11 | {
12 | label: 'Company',
13 | value: {
14 | type: 'string',
15 | value: (companyResult && companyResult.name) || NO_DATA
16 | }
17 | },
18 | {
19 | label: 'Location',
20 | value: {
21 | type: 'string',
22 | value: (locationResult && locationResult.name) || NO_DATA
23 | }
24 | }
25 | ];
26 |
27 | const itemTwo = [
28 | {
29 | label: 'Email',
30 | value: {
31 | type: 'string',
32 | value: userResult.email || NO_DATA
33 | }
34 | },
35 | {
36 | label: 'Business Phone',
37 | value: {
38 | type: 'string',
39 | value: userResult.phone || NO_DATA
40 | }
41 | },
42 | {
43 | label: 'City',
44 | value: {type: 'string', value: userResult.city || NO_DATA}
45 | }
46 | ];
47 |
48 | return {
49 | itemOne,
50 | itemTwo,
51 | name,
52 | photo
53 | };
54 | }
55 |
--------------------------------------------------------------------------------
/src/customer-360-example/getHttpEffect.js:
--------------------------------------------------------------------------------
1 | import {createHttpEffect} from '@servicenow/ui-effect-http';
2 |
3 | export const getHttpEffect = ({successActionType, errorActionType}) => {
4 | return createHttpEffect('/api/now/table/:table/:sysId', {
5 | pathParams: ['sysId', 'table'],
6 | successActionType,
7 | errorActionType
8 | });
9 | };
10 |
--------------------------------------------------------------------------------
/src/customer-360-example/index.js:
--------------------------------------------------------------------------------
1 | import './customer360';
2 |
--------------------------------------------------------------------------------
/src/customer-360-example/styles.scss:
--------------------------------------------------------------------------------
1 | @import '@servicenow/sass-kit/host';
2 |
3 | :host {
4 | height: 100%;
5 | }
6 | .customer-360 {
7 | display: flex;
8 | flex-direction: column;
9 | justify-content: center;
10 | width: now-fn-px2rem(480px);
11 | height: inherit;
12 | border: 1px solid RGB($now-color--divider-secondary);
13 | padding: $now-global-space--md;
14 | background-color: RGB($now-color--background-primary);
15 | header {
16 | width: 100%;
17 | padding-left: $now-global-space--sm;
18 | border-bottom: 1px solid RGB($now-color--divider-secondary);
19 | }
20 | .no-data {
21 | display: grid;
22 | justify-content: center;
23 | justify-items: center;
24 | grid-gap: $now-global-space--md;
25 | }
26 | .customer-details {
27 | display: grid;
28 | grid-template-columns: now-fn-px2rem(80px) now-fn-px2rem(360px);
29 | grid-gap: $now-global-space--md;
30 | padding: $now-global-space--md 0px;
31 | .caller-avatar {
32 | text-align: center;
33 | cursor: pointer;
34 | grid-row: 1/3;
35 | }
36 | now-heading {
37 | cursor: pointer;
38 | align-self: center;
39 | margin-top: $now-global-space--sm;
40 | }
41 | now-label-value-stacked {
42 | grid-column: 2/3;
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/customer-360-example/view.js:
--------------------------------------------------------------------------------
1 | import {Fragment} from '@servicenow/ui-renderer-snabbdom';
2 | import {OPEN_USER_DETAILS} from './constants';
3 | import getCallerData from './getCallerData';
4 | import '@servicenow/now-heading';
5 | import '@servicenow/now-label-value';
6 | import '@servicenow/now-loader';
7 | import '@servicenow/now-icon';
8 |
9 | const customerDetails = (
10 | userResult,
11 | locationResult,
12 | companyResult,
13 | dispatch
14 | ) => {
15 | const dataFormat = getCallerData(userResult, locationResult, companyResult);
16 |
17 | if (!Object.keys(userResult).length)
18 | return (
19 |
20 |
21 |
22 |
23 | );
24 |
25 | return (
26 |
27 |
30 |
31 | {
34 | dispatch(OPEN_USER_DETAILS);
35 | }}>
36 |
43 |
44 | {
48 | dispatch(OPEN_USER_DETAILS);
49 | }}
50 | />
51 |
58 |
65 |
66 |
67 | );
68 | };
69 |
70 | export default (state, {dispatch}) => {
71 | const {userResult, isLoading, locationResult, companyResult} = state;
72 |
73 | return (
74 |
75 | {isLoading ? (
76 |
77 | ) : (
78 | customerDetails(userResult, locationResult, companyResult, dispatch)
79 | )}
80 |
81 | );
82 | };
83 |
--------------------------------------------------------------------------------
/src/flash-card-example/constants.js:
--------------------------------------------------------------------------------
1 | export const CARDS = [
2 | {
3 | title: '',
4 | description:
5 | 'A placeholder inside a web component that users can fill with their own markup',
6 | attributes: [
7 | {
8 | title: 'name',
9 | description: 'The name of the slot.'
10 | }
11 | ]
12 | },
13 | {
14 | title: '