├── .gitignore ├── Bestpractices.md ├── README.md └── v2 ├── chat └── README.md ├── sell ├── README.md └── custom-objects-app │ ├── .gitignore │ ├── .node-version │ ├── .npmrc │ ├── .prettierrc │ ├── LICENSE │ ├── README.md │ ├── __mocks__ │ └── svgMock.js │ ├── code_style.xml │ ├── custom_objects_schema_setup.js │ ├── dist │ ├── assets │ │ ├── logo-small.png │ │ └── logo.png │ ├── manifest.json │ └── translations │ │ └── en.json │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── setupTests.ts │ ├── src │ ├── App.css │ ├── EntryView.tsx │ ├── components │ │ ├── DeleteEntryView.tsx │ │ ├── DeleteSection.css │ │ ├── DeleteSection.tsx │ │ ├── DeleteView.tsx │ │ ├── Details.tsx │ │ ├── DetailsDropdown.tsx │ │ ├── DetailsView.tsx │ │ ├── EditEntryView.tsx │ │ ├── EditForm.tsx │ │ ├── EditView.tsx │ │ ├── EmptyState.tsx │ │ ├── Form.css │ │ ├── Loader.css │ │ ├── Loader.tsx │ │ ├── NewForm.tsx │ │ └── NewView.tsx │ ├── index.test.tsx │ ├── index.tsx │ ├── providers │ │ └── sunshineProvider.ts │ └── svg │ │ └── EmptyState.svg │ ├── tsconfig.json │ ├── tslint.json │ ├── typings.d.ts │ └── webpack.config.js ├── sunshine ├── .DS_Store ├── README.md ├── notely_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── logo-small.png │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── ticket_sidebar.html │ │ └── user_sidebar.html │ ├── images │ │ ├── download.png │ │ ├── install.png │ │ ├── load-unsafe-scripts.png │ │ ├── manage-apps.png │ │ ├── screenshot.png │ │ ├── security.png │ │ ├── upload.png │ │ └── url.png │ ├── manifest.json │ └── translations │ │ └── en.json ├── notely_timeline_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── logo-small.png │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── ticket_sidebar.html │ │ └── user_sidebar.html │ ├── images │ │ └── screenshot.png │ ├── manifest.json │ └── translations │ │ └── en.json └── user_profiles_app │ ├── README.md │ ├── assets │ ├── index.html │ ├── logo-small.png │ ├── logo.png │ ├── logo.svg │ └── styles.css │ ├── manifest.json │ ├── node_modules │ └── .yarn-integrity │ ├── translations │ └── en.json │ └── yarn.lock ├── support ├── README.md ├── basic_ticket_sample_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── iframe.html │ │ ├── logo-small.png │ │ ├── logo.png │ │ └── logo.svg │ ├── manifest.json │ └── translations │ │ └── en.json ├── garden_sample_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── icon_nav_bar.svg │ │ ├── iframe.html │ │ ├── logo-small.png │ │ ├── logo.png │ │ └── logo.svg │ ├── manifest.json │ └── translations │ │ └── en.json ├── instances_sample_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── iframe.html │ │ ├── logo-small.png │ │ ├── logo.png │ │ └── logo.svg │ ├── manifest.json │ └── translations │ │ └── en.json ├── modal_sample_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── iframe.html │ │ ├── logo-small.png │ │ ├── logo.png │ │ ├── logo.svg │ │ └── styles.css │ ├── manifest.json │ └── translations │ │ └── en.json ├── my_cat_sample_app │ ├── README.md │ ├── assets │ │ ├── iframe.html │ │ ├── logo-small.png │ │ ├── logo.png │ │ ├── logo.svg │ │ ├── main.js │ │ └── styles.css │ ├── manifest.json │ └── translations │ │ └── en.json ├── requirements_only_sample_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── logo-small.png │ │ ├── logo.png │ │ └── logo.svg │ ├── manifest.json │ ├── requirements.json │ └── translations │ │ └── en.json ├── requirements_sample_app │ ├── LICENSE │ ├── README.md │ ├── assets │ │ ├── iframe.html │ │ ├── logo-small.png │ │ ├── logo.png │ │ └── logo.svg │ ├── manifest.json │ ├── requirements.json │ └── translations │ │ └── en.json └── secure_settings_sample_app │ ├── README.md │ ├── assets │ ├── iframe.html │ ├── logo-small.png │ ├── logo.png │ ├── logo.svg │ └── styles.css │ ├── manifest.json │ └── translations │ └── en.json └── zis └── zendesk_app_as_admin_ui ├── README.md ├── part_1 ├── .gitignore ├── README.md └── src │ ├── assets │ ├── bootstrap.js │ ├── connect.js │ ├── index.html │ ├── logo-small.png │ ├── logo.png │ └── logo.svg │ ├── manifest.json │ └── translations │ └── en.json ├── part_2 ├── .gitignore ├── README.md └── src │ ├── assets │ ├── bootstrap.js │ ├── config.js │ ├── connect.js │ ├── index.html │ ├── logo-small.png │ ├── logo.png │ └── logo.svg │ ├── manifest.json │ └── translations │ └── en.json └── part_3 ├── .gitignore ├── README.md └── src ├── assets ├── bootstrap.js ├── bundle.js ├── config.js ├── connect.js ├── index.html ├── logo-small.png ├── logo.png ├── logo.svg └── registry.js ├── manifest.json └── translations └── en.json /.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | **/.zat 3 | **/tmp 4 | *.swp 5 | **/zcli.apps.config.json 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /Bestpractices.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | All Zendesk Apps should follow a set of best practices. These best practices can help on various levels, and make it easier for you to ensure your App will not impact your Zendesk's performance or deteriorate the Agent's experience. Additionally, following these best practices will help you migrate framework versions much faster and smoother, breaking changes can potentially be avoided by following some of these guidelines. 4 | 5 | All public Apps have to go through an approval process. This document is also aimed at helping you pass the approval process with flying colors from the first submission. 6 | 7 | Whether you are building an App for your own company or for all of Zendesk customers we strongly encourage you to follow these guidelines and best practices. 8 | 9 | If you aren't sure about any of the points below, if you have questions about the approval process or if you would like to receive guidance or help building your first Zendesk App, please feel free to get in touch at support@zendesk.com. 10 | 11 | ## Best Practices 12 | 13 | * Use the [CDN framework version](https://developer.zendesk.com/apps/docs/developer-guide/using_sdk#getting-the-sdk). 14 | 15 | * Use [Zendesk Garden](https://developer.zendesk.com/apps/docs/developer-guide/setup#using-zendesk-garden) from NPM. 16 | 17 | * [Don't Repeat Yourself](https://en.wikipedia.org/wiki/Don't_repeat_yourself). Be critical of your own app, if you see that you've repeatedly done the same thing in your code then look to simplify by making helper functions that can be used in more than one place. 18 | 19 | * Cleanup. Use life-cycle events `app.deactivated` and `app.willDestroy` to tidy up your app's state. The intent for these events, and a general best practice, is to cleanup anything that your app might have set up that is no longer needed and might impact on performance of the product it is running in. A prime candidate for cleanup would be intervals you've created via `setInterval` or `setTimeout`. App developers should always store a reference to an ID returned from either of the above methods so as to be able to call `clearInterval` or `clearTimeout`. 20 | 21 | * Use promises to handle asynchronous instructions. See [JavaScript Promises: an Introduction](https://developers.google.com/web/fundamentals/getting-started/primers/promises) on Google's developer portal for a great introduction to JavaScript promises. 22 | 23 | * Cache the result of promises and API requests when the data doesn't change often. 24 | 25 | * Use [secure settings](https://developer.zendesk.com/apps/docs/apps-v2/using_sdk#using-secure-settings) for any sensitive setting, like API tokens and/or passwords. 26 | 27 | * Use a [`domainWhitelist`](https://developer.zendesk.com/apps/docs/developer-guide/using_sdk#example) when using secure settings. 28 | 29 | * Don't attempt to read secure settings, it won't work. Secure settings can only be used as placeholders that get replaced by the server. 30 | 31 | * When making Ajax requests to the Zendesk API, avoid requesting all pages in a loop. If you must get all the data, make sure to add a delay between calls to avoid rate limiting. 32 | 33 | * Check out our [changelog](https://developer.zendesk.com/apps/docs/apps-v2/changelog) frequently to keep up to date with the latest framework updates. 34 | 35 | * Make sure you define an app version. An app version will help you, and anyone else using the app keep track of what is installed. This can be particularly helpful if a bug is found and you need to provide a newer version of an app. 36 | 37 | * When [creating a ticket in telephony apps](https://support.zendesk.com/entries/24539263#topic_o32_xv1_sk), be sure that you're setting the via_id to 44 (voicemail), 45 (inbound call), or 46 (outbound call) depending on the type of call. This ensures that Zendesk admins and agents are able to properly report on these tickets within Zendesk. 38 | 39 | * Prefer [bulk calls](https://developer.zendesk.com/apps/docs/apps-v2/using_sdk#bulk-calls) over single calls whenever possible. 40 | 41 | * Specify `autoLoad: false` for locations where you don't need to display a user interface and use the `background` location with the Instances API to interact with those locations. This reduces the number of iframes that need to be created for your app, thus saving Memory and CPU. See [Instances API Sample App](https://github.com/zendesk/demo_apps/tree/master/v2/support/instances_sample_app) for an example of this technique. 42 | 43 | * Use the [App Scaffold](https://github.com/zendesk/app_scaffold/tree/from-scratch)'s from-scratch branch when starting development of any non-trivial app. The App Scaffold includes many features to help you maintain and scale your app. 44 | 45 | * Use [signed urls](https://developer.zendesk.com/apps/docs/apps-v2/using_sdk#authenticating-requests-with-signed-urls) to verify the request is legitimate when developing server-side apps. 46 | 47 | * Clean up console.log and debugger statements before submitting your app. 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Sample Apps 4 | 5 | This repository provides you with sample Apps to help learn how to use the Zendesk Apps framework and APIs. 6 | 7 | * [ZAF v2 demo apps](./v2) 8 | * [Support APIs](./v2/support) 9 | * [Chat APIs](./v2/chat) 10 | * [Sunshine APIs](./v2/sunshine) 11 | * [Sell APIs](./v2/sell) 12 | * [ZIS](./v2/zis) 13 | 14 | We hope you'll find those sample Apps useful and encourage you to re-use some of this code in your own Apps. If you have any questions please email support@zendesk.com or find us on [Twitter](https://twitter.com/zendesk). Please submit bug reports to [Zendesk](https://support.zendesk.com/requests/new). Pull requests are welcome. 15 | -------------------------------------------------------------------------------- /v2/chat/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Chat Sample Apps 4 | 5 | This repository provides you with sample Apps to help learn how to use the Zendesk Apps framework v2 and Zendesk Chat APIs. 6 | -------------------------------------------------------------------------------- /v2/sell/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Sell sample apps 4 | 5 | This repository provides you with sample apps to help learn how to use the Zendesk Apps framework v2 and Zendesk Sell APIs. 6 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | .idea 63 | .vscode 64 | 65 | /dist/assets/index.html 66 | /dist/assets/*.bundle.* 67 | /dist/tmp/ 68 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/.node-version: -------------------------------------------------------------------------------- 1 | 22.14.0 2 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true 2 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "tabWidth": 2, 4 | "semi": false, 5 | "bracketSpacing": false, 6 | "jsxBracketSameLine": false, 7 | "printWidth": 80, 8 | "singleQuote": true, 9 | "arrowParens": "always" 10 | } 11 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/__mocks__/svgMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {default: 'svg'}; 2 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/code_style.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/custom_objects_schema_setup.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch') 2 | // REQUIREMENTS: 3 | // 1. Activate Sunshine Custom objects on UI 4 | // 2. Get credentials 5 | // https://developer.zendesk.com/rest_api/docs/support/introduction#api-token 6 | const ACCESS_TOKEN = '' 7 | const MAIL = '' 8 | const SUBDOMAIN = '' 9 | 10 | const TOKEN = Buffer.from(`${MAIL}/token:${ACCESS_TOKEN}`).toString('base64') 11 | const ENVIRONMENT = 'zendesk-staging.com' 12 | 13 | const headers = { 14 | 'Content-Type': 'application/json', 15 | Accept: 'application/json', 16 | Authorization: `Basic ${TOKEN}`, 17 | } 18 | 19 | const createType = async (path, data) => { 20 | const result = await fetch( 21 | `https://${SUBDOMAIN}.${ENVIRONMENT}/api/sunshine/${path}`, 22 | { 23 | body: JSON.stringify(data), 24 | method: 'POST', 25 | headers, 26 | }, 27 | ) 28 | return result.json() 29 | } 30 | 31 | const invoiceTypeSchema = { 32 | data: { 33 | key: 'invoice', 34 | schema: { 35 | properties: { 36 | invoice_number: { 37 | type: 'string', 38 | description: 'Invoice number', 39 | }, 40 | issue_date: { 41 | type: 'string', 42 | description: 'Invoice date', 43 | }, 44 | due_date: { 45 | type: 'string', 46 | description: 'Date due', 47 | }, 48 | due_amount: { 49 | type: 'number', 50 | description: 'Due amount', 51 | }, 52 | is_paid: { 53 | type: 'boolean', 54 | description: 'Is paid', 55 | }, 56 | }, 57 | required: [ 58 | 'invoice_number', 59 | 'issue_date', 60 | 'due_date', 61 | 'due_amount', 62 | 'is_paid', 63 | ], 64 | }, 65 | }, 66 | } 67 | 68 | const dealInvoiceRelationTypeSchema = { 69 | data: { 70 | key: 'deal_invoice', 71 | source: 'zen:deal', 72 | target: 'invoice', 73 | }, 74 | } 75 | 76 | const handleCreatedRelationType = (response) => { 77 | console.log('Relation type:', '\n', response.data, '\n') 78 | console.log('Setup is ready. Please follow the next steps of tutorial.') 79 | } 80 | 81 | const handleCreatedObjectType = (response) => { 82 | if (response.data === undefined) { 83 | console.log('Error:', '\n', response) 84 | } else { 85 | console.log('Object type:', '\n', response.data, '\n') 86 | createType('relationships/types', dealInvoiceRelationTypeSchema).then( 87 | handleCreatedRelationType, 88 | ) 89 | } 90 | } 91 | 92 | createType('objects/types', invoiceTypeSchema).then(handleCreatedObjectType) 93 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/dist/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sell/custom-objects-app/dist/assets/logo-small.png -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/dist/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sell/custom-objects-app/dist/assets/logo.png -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Invoice", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://www.zendesk.com" 7 | }, 8 | 9 | "defaultLocale": "en", 10 | "private": false, 11 | "singleInstall": true, 12 | 13 | "location": { 14 | "sell": { 15 | "deal_card": { 16 | "url": "assets/index.html" 17 | } 18 | } 19 | }, 20 | 21 | "version": "2.0.3", 22 | "frameworkVersion": "2.0" 23 | } 24 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/dist/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Invoice", 4 | "short_description": "Short description of the app", 5 | "long_description": "Long description of the app", 6 | "installation_instructions": "Installation instructions", 7 | "parameters": {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Invoice 6 | 7 | 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@zendesk/sell-zaf-app-scaffold", 3 | "version": "0.0.2", 4 | "description": "A React scaffold for developers to build Zendesk App Framework (ZAF) apps for Sell", 5 | "main": "./dist/main.js", 6 | "scripts": { 7 | "start": "webpack -w --env development", 8 | "build": "NODE_ENV=production webpack --mode production && npm run validate && zcli apps:package ./dist && echo \"Package is ready to upload to Zendesk\"", 9 | "test": "jest --env=jsdom", 10 | "server": "zcli apps:server ./dist", 11 | "validate": "zcli apps:package ./dist", 12 | "lint": "tslint --project tsconfig.json --fix", 13 | "prettier": "prettier --write \"src/**/*.{ts,tsx}\"" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/zendesk/sell-zaf-app-scaffold.git" 18 | }, 19 | "author": "", 20 | "license": "Apache-2.0", 21 | "bugs": { 22 | "url": "https://github.com/zendesk/sell-zaf-app-scaffold/issues" 23 | }, 24 | "homepage": "https://github.com/zendesk/sell-zaf-app-scaffold#readme", 25 | "dependencies": { 26 | "@zendesk/sell-zaf-app-toolbox": "github:zendesk/sell-zaf-app-toolbox#v1.0.8", 27 | "@zendeskgarden/css-variables": "^6.4.5", 28 | "@zendeskgarden/react-buttons": "^8.31.0", 29 | "@zendeskgarden/react-datepickers": "^8.31.0", 30 | "@zendeskgarden/react-dropdowns": "^8.28.2", 31 | "@zendeskgarden/react-forms": "^8.31.0", 32 | "@zendeskgarden/react-grid": "^8.28.2", 33 | "@zendeskgarden/react-loaders": "^8.28.2", 34 | "@zendeskgarden/react-tables": "^8.31.0", 35 | "@zendeskgarden/react-theming": "^8.28.2", 36 | "@zendeskgarden/react-typography": "^8.31.0", 37 | "@zendeskgarden/svg-icons": "^6.27.0", 38 | "moment": "^2.29.4", 39 | "react-router-dom": "^5.2.0", 40 | "styled-components": "^5.2.1" 41 | }, 42 | "devDependencies": { 43 | "@svgr/webpack": "^8.1.0", 44 | "@types/enzyme": "^3.10.8", 45 | "@types/enzyme-adapter-react-16": "^1.0.6", 46 | "@types/jest": "^26.0.19", 47 | "@types/react": "^17.0.0", 48 | "@types/react-dom": "^17.0.0", 49 | "@types/react-router-dom": "^5.1.7", 50 | "@types/styled-components": "^5.1.7", 51 | "@zendesk/zcli": "^1.0.0-beta.52", 52 | "autoprefixer": "^10.1.0", 53 | "clean-webpack-plugin": "^3.0.0", 54 | "css-loader": "^5.0.1", 55 | "enzyme": "^3.11.0", 56 | "enzyme-adapter-react-16": "^1.15.5", 57 | "html-webpack-plugin": "^5.6.3", 58 | "identity-obj-proxy": "^3.0.0", 59 | "jest": "^29.7.0", 60 | "postcss-flexbugs-fixes": "^5.0.2", 61 | "postcss-import": "^14.0.0", 62 | "postcss-loader": "^8.1.1", 63 | "prettier": "^2.2.1", 64 | "react": "^17.0.1", 65 | "react-dom": "^17.0.1", 66 | "source-map-loader": "^1.1.3", 67 | "style-loader": "^2.0.0", 68 | "ts-jest": "^26.4.4", 69 | "ts-loader": "^9.5.2", 70 | "tslint": "^6.1.3", 71 | "tslint-config-prettier": "^1.18.0", 72 | "tslint-origin-ordered-imports-rule": "^1.2.2", 73 | "tslint-plugin-prettier": "^2.3.0", 74 | "tslint-react": "^5.0.0", 75 | "tslint-react-hooks": "^2.2.2", 76 | "typescript": "^4.1.3", 77 | "typescript-plugin-css-modules": "^5.1.0", 78 | "webpack": "^5.94.0", 79 | "webpack-cli": "^4.2.0" 80 | }, 81 | "jest": { 82 | "verbose": false, 83 | "collectCoverageFrom": [ 84 | "src/**/*.{ts,tsx}" 85 | ], 86 | "globals": { 87 | "API_URL": "idealwith", 88 | "DEVELOPMENT": false 89 | }, 90 | "transform": { 91 | ".(ts|tsx)": "ts-jest" 92 | }, 93 | "testMatch": [ 94 | "/**/?(*.)(spec|test).ts?(x)" 95 | ], 96 | "setupFilesAfterEnv": [ 97 | "/setupTests.ts" 98 | ], 99 | "transformIgnorePatterns": [ 100 | "node_modules/(?!(@zendeskgarden)/)" 101 | ], 102 | "moduleFileExtensions": [ 103 | "ts", 104 | "tsx", 105 | "js", 106 | "json" 107 | ] 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/setupTests.ts: -------------------------------------------------------------------------------- 1 | import * as enzyme from 'enzyme' 2 | import * as Adapter from 'enzyme-adapter-react-16' 3 | 4 | enzyme.configure({adapter: new Adapter()}) 5 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/App.css: -------------------------------------------------------------------------------- 1 | @import '@zendeskgarden/css-variables'; 2 | 3 | :global(html), 4 | :global(body) { 5 | height: 100%; 6 | overflow: auto; 7 | } 8 | 9 | :global(#app) { 10 | height: 100%; 11 | } 12 | 13 | .App { 14 | height: 100%; 15 | color: var(--zd-color-grey-800); 16 | font-family: var(--zd-font-family-system); 17 | font-size: var(--zd-font-size-md-monospace); 18 | font-weight: var(--zd-font-weight-light); 19 | line-height: normal; 20 | } 21 | 22 | .header { 23 | background-color: var(--zd-color-grey-100); 24 | border-bottom: solid 1px var(--zd-color-grey-300); 25 | padding: var(--zd-spacing-sm); 26 | } 27 | 28 | .title { 29 | color: var(--zd-color-black); 30 | font-size: var(--zd-font-size-md); 31 | } 32 | 33 | .dateContainer { 34 | display: flex; 35 | flex-direction: row-reverse; 36 | padding: var(--zd-spacing-sm); 37 | } 38 | 39 | .contentView { 40 | padding: var(--zd-spacing-sm); 41 | } 42 | 43 | .icon { 44 | margin-right: var(--zd-spacing-xs); 45 | } 46 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/EntryView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { 3 | useClientHeight, 4 | ResponseHandler, 5 | useClientGet, 6 | } from '@zendesk/sell-zaf-app-toolbox' 7 | import {Row, Grid} from '@zendeskgarden/react-grid' 8 | 9 | import Loader from './components/Loader' 10 | import DetailsView from './components/DetailsView' 11 | import css from './App.css' 12 | 13 | export const EntryView = () => { 14 | useClientHeight(215) 15 | const dealIdResponse = useClientGet('deal.id') 16 | 17 | return ( 18 | 19 | 20 | } 23 | errorView={
Something went wrong!
} 24 | emptyView={
There is no Deal
} 25 | > 26 | {([dealId]: [string]) => } 27 |
28 |
29 |
30 | ) 31 | } 32 | 33 | export default EntryView 34 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/DeleteEntryView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { 3 | useClientHeight, 4 | ResponseHandler, 5 | useClientGet, 6 | } from '@zendesk/sell-zaf-app-toolbox' 7 | import {Row, Grid} from '@zendeskgarden/react-grid' 8 | 9 | import Loader from './Loader' 10 | import DeleteView from './DeleteView' 11 | import css from '../App.css' 12 | 13 | export const DeleteEntryView = () => { 14 | useClientHeight(120) 15 | const dealIdResponse = useClientGet('deal.id') 16 | 17 | return ( 18 | 19 | 20 | } 23 | errorView={
Something went wrong!
} 24 | emptyView={
There is no Deal
} 25 | > 26 | {([dealId]: [string]) => } 27 |
28 |
29 |
30 | ) 31 | } 32 | 33 | export default DeleteEntryView 34 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/DeleteSection.css: -------------------------------------------------------------------------------- 1 | @import '@zendeskgarden/css-variables'; 2 | 3 | .DeleteSection { 4 | padding-top: 15px; 5 | } 6 | 7 | .deleteHeader { 8 | margin-bottom: var(--zd-spacing) 9 | } 10 | 11 | .cancelDeleteSpacing { 12 | margin: var(--zd-spacing-sm) 13 | } 14 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/DeleteSection.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {Col, Grid, Row} from '@zendeskgarden/react-grid' 3 | import {LG} from '@zendeskgarden/react-typography' 4 | import {Button} from '@zendeskgarden/react-buttons' 5 | import {PALETTE} from '@zendeskgarden/react-theming' 6 | import {Inline} from '@zendeskgarden/react-loaders' 7 | import {Link} from 'react-router-dom' 8 | import {useState} from 'react' 9 | 10 | import {RelationshipData} from '../providers/sunshineProvider' 11 | import css from './DeleteSection.css' 12 | 13 | const DeleteSection = ({ 14 | relation, 15 | onDelete, 16 | }: { 17 | relation: RelationshipData 18 | onDelete: (relationId: string, invoiceId: string) => void 19 | }) => { 20 | const [submitted, setSubmitted] = useState(false) 21 | const handleDelete = () => { 22 | setSubmitted(true) 23 | onDelete(relation.id, relation.target) 24 | } 25 | 26 | return ( 27 | 28 | 33 | Do you want to remove the Invoice? 34 | 35 | 36 | 37 | 38 | 41 | 42 | 51 | 52 | 53 | 54 | ) 55 | } 56 | 57 | export default DeleteSection 58 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/DeleteView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { 3 | ResponseHandler, 4 | useClientRequest, 5 | ZAFClientContext, 6 | } from '@zendesk/sell-zaf-app-toolbox' 7 | import {useHistory} from 'react-router-dom' 8 | import {useCallback, useContext} from 'react' 9 | 10 | import { 11 | deleteRelation, 12 | deleteObject, 13 | RelationshipData, 14 | } from '../providers/sunshineProvider' 15 | 16 | import { 17 | RELATION_TYPE, 18 | RelationshipListResponse, 19 | } from '../providers/sunshineProvider' 20 | import Loader from './Loader' 21 | import DeleteSection from './DeleteSection' 22 | 23 | const DeleteView = ({dealId}: {dealId: string}) => { 24 | const dealRelationName = `zen:deal:${dealId}` 25 | const client = useContext(ZAFClientContext) 26 | const history = useHistory() 27 | const sunshineResponse = useClientRequest( 28 | `/api/sunshine/relationships/records?type=${RELATION_TYPE}`, 29 | ) 30 | 31 | const handleDelete = useCallback( 32 | async (relationId: string, invoiceId: string) => { 33 | await deleteRelation(client, relationId) 34 | await deleteObject(client, invoiceId) 35 | history.push('/') 36 | }, 37 | [], 38 | ) 39 | const isRelationEmpty = (response: {data: RelationshipListResponse}) => 40 | response.data.data.filter( 41 | (relation: RelationshipData) => relation.source === dealRelationName, 42 | ).length === 0 43 | 44 | return ( 45 | } 48 | errorView={
Something went wrong!
} 49 | emptyView={
Couldn't find any related invoices
} 50 | isEmpty={isRelationEmpty} 51 | > 52 | {([response]: [RelationshipListResponse]) => ( 53 | 57 | relation.source === dealRelationName, 58 | ) as RelationshipData 59 | } 60 | onDelete={handleDelete} 61 | /> 62 | )} 63 |
64 | ) 65 | } 66 | 67 | export default DeleteView 68 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/Details.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import moment from 'moment' 3 | import { 4 | Body, 5 | Cell, 6 | Head, 7 | HeaderCell, 8 | HeaderRow, 9 | Row as TableRow, 10 | Table, 11 | } from '@zendeskgarden/react-tables' 12 | import {Code, MD} from '@zendeskgarden/react-typography' 13 | import {Grid, Row} from '@zendeskgarden/react-grid' 14 | 15 | import {InvoiceData} from '../providers/sunshineProvider' 16 | import DetailsDropdown from './DetailsDropdown' 17 | 18 | const Details = ({ 19 | invoice, 20 | onEdit, 21 | onDelete, 22 | }: { 23 | invoice: InvoiceData 24 | onEdit: () => void 25 | onDelete: () => void 26 | }) => { 27 | const { 28 | invoice_number, 29 | issue_date, 30 | due_date, 31 | due_amount, 32 | is_paid, 33 | } = invoice.attributes 34 | 35 | return ( 36 | 37 | 38 | 39 | 40 | 41 | Invoice number 42 | 43 | {invoice_number} 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Issue date 54 | 55 | 56 | {moment(issue_date).format('ll')} 57 | 58 | 59 | 60 | 61 | 62 | Due date 63 | 64 | 65 | {moment(due_date).format('ll')} 66 | 67 | 68 | 69 | 70 | 71 | Due amount 72 | 73 | ${due_amount} 74 | 75 | 76 | 77 | 78 | Status 79 | 80 | 81 | {is_paid ? ( 82 | Paid 83 | ) : ( 84 | Not Paid 85 | )} 86 | 87 | 88 | 89 | 90 |
91 |
92 |
93 | ) 94 | } 95 | 96 | export default Details 97 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/DetailsDropdown.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {OverflowButton} from '@zendeskgarden/react-tables' 3 | import {Dropdown, Menu, Item, Trigger} from '@zendeskgarden/react-dropdowns' 4 | 5 | enum InvoiceActions { 6 | Delete = 'delete', 7 | Edit = 'edit', 8 | } 9 | 10 | const DetailsDropdown = ({ 11 | onEdit, 12 | onDelete, 13 | }: { 14 | onEdit: () => void 15 | onDelete: () => void 16 | }) => { 17 | const handleSelect = (action: InvoiceActions) => { 18 | switch (action) { 19 | case InvoiceActions.Delete: 20 | onDelete() 21 | break 22 | case InvoiceActions.Edit: 23 | onEdit() 24 | break 25 | } 26 | } 27 | 28 | return ( 29 | 30 | 31 | 35 | 36 | { 47 | data.offsets.popper.top -= 2 48 | 49 | return data 50 | }, 51 | }, 52 | }} 53 | > 54 | 55 | Edit 56 | 57 | 58 | Delete 59 | 60 | 61 | 62 | ) 63 | } 64 | 65 | export default DetailsDropdown 66 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/DetailsView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {useCallback} from 'react' 3 | 4 | import {ResponseHandler, useClientRequest} from '@zendesk/sell-zaf-app-toolbox' 5 | 6 | import {useHistory} from 'react-router-dom' 7 | 8 | import Loader from './Loader' 9 | import EmptyState from './EmptyState' 10 | import {InvoiceListResponse} from '../providers/sunshineProvider' 11 | import Details from './Details' 12 | 13 | const DetailsView = ({dealId}: {dealId: string}) => { 14 | const history = useHistory() 15 | const sunshineResponse = useClientRequest( 16 | `/api/sunshine/objects/records/zen:deal:${dealId}/related/deal_invoice`, 17 | ) 18 | 19 | const handleEdit = useCallback(() => history.push('/edit'), []) 20 | const handleDelete = useCallback(() => history.push('/delete'), []) 21 | 22 | const isInvoiceListEmpty = (response: {data: InvoiceListResponse}) => 23 | response.data.data.length === 0 24 | 25 | return ( 26 | } 29 | errorView={
Something went wrong!
} 30 | emptyView={} 31 | isEmpty={isInvoiceListEmpty} 32 | > 33 | {([response]: [InvoiceListResponse]) => ( 34 |
39 | )} 40 | 41 | ) 42 | } 43 | 44 | export default DetailsView 45 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/EditEntryView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import { 3 | useClientHeight, 4 | ResponseHandler, 5 | useClientGet, 6 | } from '@zendesk/sell-zaf-app-toolbox' 7 | import {Row, Grid} from '@zendeskgarden/react-grid' 8 | 9 | import Loader from './Loader' 10 | import EditView from './EditView' 11 | import css from '../App.css' 12 | 13 | export const EditEntryView = () => { 14 | useClientHeight(390) 15 | const dealIdResponse = useClientGet('deal.id') 16 | 17 | return ( 18 | 19 | 20 | } 23 | errorView={
Something went wrong!
} 24 | emptyView={
There is no Deal
} 25 | > 26 | {([dealId]: [string]) => } 27 |
28 |
29 |
30 | ) 31 | } 32 | 33 | export default EditEntryView 34 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/EditForm.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {Datepicker} from '@zendeskgarden/react-datepickers' 3 | import {Field, Label, Input, Checkbox} from '@zendeskgarden/react-forms' 4 | import {Row, Col, Grid} from '@zendeskgarden/react-grid' 5 | import {Button} from '@zendeskgarden/react-buttons' 6 | import {useCallback, useState} from 'react' 7 | import {Link} from 'react-router-dom' 8 | import {InvoiceData} from 'src/providers/sunshineProvider' 9 | import {Inline} from '@zendeskgarden/react-loaders' 10 | 11 | import css from './Form.css' 12 | 13 | export interface EditFormAttributes { 14 | dealId: number 15 | invoiceNumber: string 16 | issueDate: Date 17 | dueDate: Date 18 | dueAmount: string 19 | isPaid: boolean 20 | } 21 | 22 | const EditForm = ({ 23 | invoice, 24 | onSubmittedForm, 25 | }: { 26 | invoice: InvoiceData 27 | onSubmittedForm: (invoiceId: string, attributes: EditFormAttributes) => void 28 | }) => { 29 | const invoiceAttributes = invoice.attributes 30 | const [submitted, setSubmitted] = useState(false) 31 | const [attributes, setAttributes] = useState({ 32 | invoiceNumber: invoiceAttributes.invoice_number, 33 | issueDate: new Date(invoiceAttributes.issue_date), 34 | dueDate: new Date(invoiceAttributes.due_date), 35 | dueAmount: invoiceAttributes.due_amount.toString(), 36 | isPaid: invoiceAttributes.is_paid, 37 | }) 38 | 39 | const handleSubmit = useCallback(() => { 40 | setSubmitted(true) 41 | onSubmittedForm(invoice.id, {...attributes} as EditFormAttributes) 42 | }, [attributes]) 43 | 44 | const handleInvoiceNumber = useCallback( 45 | (event: {target: {value: string}}) => 46 | setAttributes({...attributes, invoiceNumber: event.target.value}), 47 | [attributes], 48 | ) 49 | 50 | const handleIssueDate = useCallback( 51 | (issueDate: Date) => setAttributes({...attributes, issueDate}), 52 | [attributes], 53 | ) 54 | 55 | const handleDueDate = useCallback( 56 | (dueDate: Date) => setAttributes({...attributes, dueDate}), 57 | [attributes], 58 | ) 59 | 60 | const handleDueAmount = useCallback( 61 | (event: {target: {value: string}}) => 62 | setAttributes({...attributes, dueAmount: event.target.value}), 63 | [attributes], 64 | ) 65 | 66 | const handleIsPaid = useCallback( 67 | () => setAttributes({...attributes, isPaid: !attributes.isPaid}), 68 | [attributes], 69 | ) 70 | 71 | const isButtonDisabled = () => 72 | attributes.invoiceNumber.length === 0 || attributes.dueAmount.length === 0 73 | 74 | return ( 75 | 76 | 77 | 78 | 79 | 80 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 106 | 107 | 108 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 124 | 125 | 134 | 135 | 136 | 137 | ) 138 | } 139 | 140 | export default EditForm 141 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/EditView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {useHistory} from 'react-router-dom' 3 | import { 4 | ResponseHandler, 5 | useClientRequest, 6 | ZAFClientContext, 7 | } from '@zendesk/sell-zaf-app-toolbox' 8 | import {useCallback, useContext} from 'react' 9 | 10 | import {updateInvoice, InvoiceListResponse} from '../providers/sunshineProvider' 11 | import Loader from './Loader' 12 | import EditForm, {EditFormAttributes} from './EditForm' 13 | 14 | const EditView = ({dealId}: {dealId: string}) => { 15 | const history = useHistory() 16 | const client = useContext(ZAFClientContext) 17 | 18 | const sunshineResponse = useClientRequest( 19 | `/api/sunshine/objects/records/zen:deal:${dealId}/related/deal_invoice`, 20 | ) 21 | 22 | const handleSubmittedForm = useCallback( 23 | async (invoiceId: string, attributes: EditFormAttributes) => { 24 | await updateInvoice(client, invoiceId, attributes) 25 | history.push('/') 26 | }, 27 | [], 28 | ) 29 | const isInvoiceListEmpty = (response: {data: InvoiceListResponse}) => 30 | response.data.data.length === 0 31 | 32 | return ( 33 | } 36 | errorView={
Something went wrong!
} 37 | emptyView={
Couldn't find any related invoices
} 38 | isEmpty={isInvoiceListEmpty} 39 | > 40 | {([response]: [InvoiceListResponse]) => ( 41 | 45 | )} 46 |
47 | ) 48 | } 49 | 50 | export default EditView 51 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/EmptyState.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {Row, Col} from '@zendeskgarden/react-grid' 3 | import {Button} from '@zendeskgarden/react-buttons' 4 | import {Link} from 'react-router-dom' 5 | 6 | import EmptyStateSVG from './../svg/EmptyState.svg' 7 | import css from './../App.css' 8 | 9 | const EmptyState = () => { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 20 | 21 | 22 | 23 | ) 24 | } 25 | 26 | export default EmptyState 27 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/Form.css: -------------------------------------------------------------------------------- 1 | @import '@zendeskgarden/css-variables'; 2 | 3 | .Form { 4 | height: 100%; 5 | padding-top: var(--zd-spacing-xs); 6 | padding-bottom: var(--zd-spacing-xs); 7 | } 8 | 9 | .submitButtonsSpacing { 10 | margin: var(--zd-spacing-sm) 11 | } 12 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/Loader.css: -------------------------------------------------------------------------------- 1 | .loaderContainer { 2 | padding-top: var(--zd-spacing-sm); 3 | padding-bottom: var(--zd-spacing-sm); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/Loader.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {Spinner} from '@zendeskgarden/react-loaders' 3 | import {Col} from '@zendeskgarden/react-grid' 4 | 5 | import css from './Loader.css' 6 | 7 | const Loader = () => { 8 | return ( 9 | 10 | 11 | 12 | ) 13 | } 14 | 15 | export default Loader 16 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/NewForm.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {Datepicker} from '@zendeskgarden/react-datepickers' 3 | import {Field, Label, Input, Checkbox} from '@zendeskgarden/react-forms' 4 | import {Row, Col, Grid} from '@zendeskgarden/react-grid' 5 | import {Button} from '@zendeskgarden/react-buttons' 6 | import {Inline} from '@zendeskgarden/react-loaders' 7 | import {useCallback, useState} from 'react' 8 | import {Link} from 'react-router-dom' 9 | 10 | import css from './Form.css' 11 | 12 | export interface NewFormAttributes { 13 | dealId: number 14 | invoiceNumber: string 15 | issueDate: Date 16 | dueDate: Date 17 | dueAmount: string 18 | isPaid: boolean 19 | } 20 | 21 | const NewForm = ({ 22 | dealId, 23 | onSubmittedForm, 24 | }: { 25 | dealId: number 26 | onSubmittedForm: (attributes: NewFormAttributes) => void 27 | }) => { 28 | const [attributes, setAttributes] = useState({ 29 | invoiceNumber: '', 30 | issueDate: new Date(), 31 | dueDate: new Date(), 32 | dueAmount: '', 33 | isPaid: false, 34 | }) 35 | 36 | const [submitted, setSubmitted] = useState(false) 37 | 38 | const handleSubmit = useCallback(() => { 39 | setSubmitted(true) 40 | onSubmittedForm({...attributes, dealId}) 41 | }, [attributes]) 42 | 43 | const handleInvoiceNumber = useCallback( 44 | (event: {target: {value: string}}) => 45 | setAttributes({...attributes, invoiceNumber: event.target.value}), 46 | [attributes], 47 | ) 48 | 49 | const handleIssueDate = useCallback( 50 | (issueDate: Date) => setAttributes({...attributes, issueDate}), 51 | [attributes], 52 | ) 53 | 54 | const handleDueDate = useCallback( 55 | (dueDate: Date) => setAttributes({...attributes, dueDate}), 56 | [attributes], 57 | ) 58 | 59 | const handleDueAmount = useCallback( 60 | (event: {target: {value: string}}) => 61 | setAttributes({...attributes, dueAmount: event.target.value}), 62 | [attributes], 63 | ) 64 | 65 | const handleIsPaid = useCallback( 66 | () => setAttributes({...attributes, isPaid: !attributes.isPaid}), 67 | [attributes], 68 | ) 69 | 70 | const isButtonDisabled = () => 71 | attributes.invoiceNumber.length === 0 || attributes.dueAmount.length === 0 72 | 73 | return ( 74 | 75 | 76 | 77 | 78 | 79 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 105 | 106 | 107 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 123 | 124 | 133 | 134 | 135 | 136 | ) 137 | } 138 | 139 | export default NewForm 140 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/components/NewView.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import {useHistory} from 'react-router-dom' 3 | import { 4 | ResponseHandler, 5 | useClientGet, 6 | useClientHeight, 7 | ZAFClientContext, 8 | } from '@zendesk/sell-zaf-app-toolbox' 9 | import {useCallback, useContext} from 'react' 10 | 11 | import { 12 | createInvoice, 13 | createRelation, 14 | InvoiceResponse, 15 | } from '../providers/sunshineProvider' 16 | import Loader from './Loader' 17 | import NewForm, {NewFormAttributes} from './NewForm' 18 | 19 | const NewView = () => { 20 | useClientHeight(400) 21 | const history = useHistory() 22 | const dealIdResponse = useClientGet('deal.id') 23 | const client = useContext(ZAFClientContext) 24 | 25 | const handleSubmittedForm = useCallback( 26 | async (attributes: NewFormAttributes) => { 27 | const invoiceResponse = (await createInvoice( 28 | client, 29 | attributes, 30 | )) as InvoiceResponse 31 | await createRelation(client, attributes.dealId, invoiceResponse.data.id) 32 | history.push('/') 33 | }, 34 | [], 35 | ) 36 | 37 | return ( 38 | } 41 | errorView={
Something went wrong!
} 42 | emptyView={
There's nothing to see yet.
} 43 | > 44 | {([dealId]: [number]) => ( 45 | 46 | )} 47 |
48 | ) 49 | } 50 | 51 | export default NewView 52 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/index.test.tsx: -------------------------------------------------------------------------------- 1 | describe('Example description', () => { 2 | test('example test', () => { 3 | expect(true).toBe(true) 4 | }) 5 | }) 6 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import * as ReactDOM from 'react-dom' 3 | import {useMemo} from 'react' 4 | import {BrowserRouter as Router, Switch, Route} from 'react-router-dom' 5 | 6 | import {ZAFClientContextProvider, Client} from '@zendesk/sell-zaf-app-toolbox' 7 | import {ThemeProvider} from '@zendeskgarden/react-theming' 8 | 9 | import EntryView from './EntryView' 10 | import NewView from './components/NewView' 11 | import DeleteEntryView from './components/DeleteEntryView' 12 | import EditEntryView from './components/EditEntryView' 13 | 14 | declare var ZAFClient: { 15 | init: () => Client 16 | } 17 | 18 | const App = () => { 19 | const client = useMemo(() => ZAFClient.init(), []) 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ) 34 | } 35 | 36 | ReactDOM.render(, document.getElementById('app')) 37 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/providers/sunshineProvider.ts: -------------------------------------------------------------------------------- 1 | import {Client} from '@zendesk/sell-zaf-app-toolbox' 2 | 3 | import {EditFormAttributes} from '../components/EditForm' 4 | import {NewFormAttributes} from '../components/NewForm' 5 | 6 | const OBJECT_TYPE = 'invoice' 7 | export const RELATION_TYPE = 'deal_invoice' 8 | 9 | export interface InvoiceResponse { 10 | data: InvoiceData 11 | } 12 | export interface InvoiceListResponse { 13 | data: InvoiceData[] 14 | links: Links 15 | } 16 | export interface InvoiceData { 17 | type: string 18 | id: string 19 | external_id: string 20 | attributes: InvoiceAttributes 21 | created_at: string 22 | updated_at: string 23 | } 24 | 25 | export interface InvoiceAttributes { 26 | invoice_number: string 27 | issue_date: string 28 | due_date: string 29 | due_amount: number 30 | is_paid: boolean 31 | } 32 | 33 | export interface RelationshipListResponse { 34 | data: RelationshipData[] 35 | links: Links 36 | } 37 | 38 | export interface RelationshipData { 39 | id: string 40 | relationship_type: string 41 | source: string 42 | target: string 43 | created_at: string 44 | } 45 | 46 | interface Links { 47 | previous: string 48 | next: string 49 | } 50 | 51 | export const createInvoice = ( 52 | client: Client | undefined, 53 | attributes: NewFormAttributes, 54 | ) => { 55 | const body = { 56 | data: { 57 | type: OBJECT_TYPE, 58 | attributes: { 59 | invoice_number: attributes.invoiceNumber, 60 | issue_date: attributes.issueDate, 61 | due_date: attributes.dueDate, 62 | due_amount: parseFloat(attributes.dueAmount), 63 | is_paid: attributes.isPaid, 64 | }, 65 | }, 66 | } 67 | 68 | return client?.request({ 69 | url: `/api/sunshine/objects/records`, 70 | method: 'POST', 71 | contentType: 'application/json', 72 | data: JSON.stringify(body), 73 | }) 74 | } 75 | 76 | export const updateInvoice = ( 77 | client: Client | undefined, 78 | invoiceId: string, 79 | attributes: EditFormAttributes, 80 | ) => { 81 | const body = { 82 | data: { 83 | attributes: { 84 | invoice_number: attributes.invoiceNumber, 85 | issue_date: attributes.issueDate, 86 | due_date: attributes.dueDate, 87 | due_amount: parseFloat(attributes.dueAmount), 88 | is_paid: attributes.isPaid, 89 | }, 90 | }, 91 | } 92 | 93 | return client?.request({ 94 | url: `/api/sunshine/objects/records/${invoiceId}`, 95 | method: 'PATCH', 96 | contentType: 'application/merge-patch+json', 97 | data: JSON.stringify(body), 98 | }) 99 | } 100 | 101 | export const createRelation = ( 102 | client: Client | undefined, 103 | dealId: number, 104 | invoiceId: string, 105 | ) => { 106 | const data = { 107 | data: { 108 | relationship_type: RELATION_TYPE, 109 | source: `zen:deal:${dealId}`, 110 | target: invoiceId, 111 | }, 112 | } 113 | 114 | return client?.request({ 115 | url: `/api/sunshine/relationships/records`, 116 | method: 'POST', 117 | contentType: 'application/json', 118 | data: JSON.stringify(data), 119 | }) 120 | } 121 | 122 | export const deleteRelation = ( 123 | client: Client | undefined, 124 | relationId: string, 125 | ) => { 126 | return client?.request({ 127 | url: `/api/sunshine/relationships/records/${relationId}`, 128 | method: 'DELETE', 129 | }) 130 | } 131 | 132 | export const deleteObject = (client: Client | undefined, objectId: string) => { 133 | return client?.request({ 134 | url: `/api/sunshine/objects/records/${objectId}`, 135 | method: 'DELETE', 136 | }) 137 | } 138 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/src/svg/EmptyState.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | Sailor Binoculars 6 | Created with Sketch. 7 | 9 | 11 | 12 | 13 | 14 | 15 | 17 | 19 | 21 | 23 | 25 | 28 | 29 | 30 | 32 | 34 | 36 | 38 | 40 | 41 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 59 | 60 | 62 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "sourceMap": true, 5 | "module": "esnext", 6 | "target": "es2015", 7 | "jsx": "react", 8 | "baseUrl": ".", 9 | "lib": [ 10 | "es6", 11 | "dom" 12 | ], 13 | "allowJs": true, 14 | "moduleResolution": "node", 15 | "rootDir": "src", 16 | "forceConsistentCasingInFileNames": true, 17 | "noImplicitReturns": true, 18 | "noImplicitThis": true, 19 | "noImplicitAny": true, 20 | "importHelpers": true, 21 | "strictNullChecks": true, 22 | "suppressImplicitAnyIndexErrors": true, 23 | "allowSyntheticDefaultImports": true, 24 | "plugins": [{ "name": "typescript-plugin-css-modules" }], 25 | "noUnusedLocals": true 26 | }, 27 | "include": [ 28 | "./typings.d.ts", 29 | "./src/**/*" 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:recommended", 4 | "tslint-react", 5 | "tslint-react-hooks", 6 | "tslint-plugin-prettier", 7 | "tslint-config-prettier" 8 | ], 9 | "linterOptions": { 10 | "exclude": [ 11 | "config/**/*.js", 12 | "node_modules/**/*.ts", 13 | "coverage/lcov-report/*.js" 14 | ] 15 | }, 16 | "rulesDirectory": ["node_modules/tslint-origin-ordered-imports-rule/dist"], 17 | "rules": { 18 | "prettier": true, 19 | "react-hooks-nesting": "error", 20 | "eofline": true, 21 | "interface-name": false, 22 | "ordered-imports": false, 23 | "jsx-boolean-value": false, 24 | "curly": false, 25 | "object-literal-sort-keys": false, 26 | "member-access": false, 27 | "origin-ordered-imports": [true, "one-blank-line"] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/typings.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' 2 | 3 | declare module '*.css' { 4 | const classes: {[key: string]: string} 5 | export default classes 6 | } 7 | -------------------------------------------------------------------------------- /v2/sell/custom-objects-app/webpack.config.js: -------------------------------------------------------------------------------- 1 | const HtmlWebpackPlugin = require('html-webpack-plugin') 2 | const autoprefixer = require('autoprefixer') 3 | const {CleanWebpackPlugin} = require('clean-webpack-plugin') 4 | 5 | module.exports = (env = {}) => { 6 | return { 7 | entry: './src/index.tsx', 8 | output: { 9 | filename: '[name].bundle.js', 10 | chunkFilename: '[name].bundle.js', 11 | path: __dirname + '/dist/assets', 12 | }, 13 | 14 | mode: 'development', 15 | 16 | // Enable sourcemaps for debugging webpack's output. 17 | devtool: env.development ? 'source-map' : false, 18 | 19 | resolve: { 20 | extensions: ['.ts', '.tsx', '.js', '.json'], 21 | }, 22 | stats: { 23 | modules: false, 24 | hash: false, 25 | version: false, 26 | }, 27 | 28 | module: { 29 | rules: [ 30 | { 31 | test: /\.svg$/, 32 | use: [ 33 | { 34 | loader: '@svgr/webpack', 35 | }, 36 | ], 37 | }, 38 | { 39 | test: /\.css$/, 40 | use: [ 41 | { 42 | loader: 'style-loader', 43 | }, 44 | { 45 | loader: 'css-loader', 46 | options: { 47 | modules: { 48 | localIdentName: '[hash:base64:3]--[name]--[local]', 49 | exportLocalsConvention: 'camelCase', 50 | }, 51 | }, 52 | }, 53 | { 54 | loader: require.resolve('postcss-loader'), 55 | options: { 56 | postcssOptions: { 57 | plugins: [ 58 | require('postcss-import'), 59 | require('postcss-flexbugs-fixes'), 60 | autoprefixer({ 61 | flexbox: 'no-2009', 62 | }), 63 | ], 64 | }, 65 | }, 66 | }, 67 | ], 68 | }, 69 | // All files with a '.ts' or '.tsx' extension will be handled/**/ by 70 | { 71 | test: /\.tsx?$/, 72 | loader: 'ts-loader', 73 | }, 74 | 75 | // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. 76 | { 77 | enforce: 'pre', 78 | test: /\.js$/, 79 | loader: 'source-map-loader', 80 | }, 81 | ], 82 | }, 83 | 84 | plugins: [ 85 | new CleanWebpackPlugin({ 86 | cleanOnceBeforeBuildPatterns: [ 87 | '**/*', 88 | '!logo.png', 89 | '!logo-small.png', 90 | '!screenshot-0.png', 91 | '!screenshot-1.png', 92 | '!screenshot-2.png', 93 | ], 94 | }), 95 | new HtmlWebpackPlugin({ 96 | filename: 'index.html', 97 | template: 'index.html', 98 | hash: true, 99 | }), 100 | // Uncomment that in order to analyze bundle size 101 | // new BundleAnalyzerPlugin(), 102 | ], 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /v2/sunshine/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/.DS_Store -------------------------------------------------------------------------------- /v2/sunshine/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Sunshine Sample Apps 4 | 5 | This repository provides you with sample Apps to help learn how to use the Zendesk Apps framework v2 and Zendesk Sunshine APIs. 6 | These apps may live in different locations across Zendesk products - or even outside of the Zendesk Apps Framework - but all depend on Zendesk Sunshine APIs. Many of these APIs are restricted to an Early Access Program. See the Sunshine community topics here for details and updates: https://develop.zendesk.com/hc/en-us/community/topics 7 | -------------------------------------------------------------------------------- /v2/sunshine/notely_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /v2/sunshine/notely_app/README.md: -------------------------------------------------------------------------------- 1 | # Notely 2 | 3 | Notely is a sample Zendesk App that allows agents to record events using the [Custom Events API](https://developer.zendesk.com/documentation/custom-data/events/about-the-events-api/). 4 | 5 | Events can be viewed in Interaction History in Agent Workspace. To learn more, see [Adding Sunshine user profiles and events to customer context in a ticket](https://support.zendesk.com/hc/en-us/articles/4408828663322) 6 | 7 | 8 | 9 | ## Table of Contents 10 | 11 | * [Installing the app as is](#installing-the-app-as-is) 12 | * [Local Development](#local-development) 13 | * [Built With](#built-with) 14 | * [License](#license) 15 | 16 | ## Installing the app as is 17 | 18 | To run the app on your Zendesk subdomain 19 | 20 | 1. Download the zip of the app 21 | 22 | 23 | 2. Go to the Zendesk Support Manage Apps page on the Admin Settings page, and click the `Upload private app` button 24 | 25 | 26 | 3. Upload the downloaded zip 27 | 28 | 29 | 4. Install the app 30 | 31 | 32 | ## Local Development 33 | Clone the repo and `cd` into the directory 34 | ``` 35 | git clone git@github.com:zendesk/notely_app.git && cd notely_app 36 | ``` 37 | 38 | Run the local dev server 39 | ``` 40 | zat server 41 | ``` 42 | 43 | Open a browser and go to your Zendesk subdomain. Append `?zat=true` to the end of your instance's url 44 | 45 | 46 | 47 | Click the security icon that pops up. 48 | 49 | 50 | 51 | Click load unsafe scripts 52 | 53 | 54 | 55 | 56 | Happy Developing :) 57 | 58 | ## Built With 59 | 60 | * [Zendesk App Framework](https://developer.zendesk.com/apps/docs/developer-guide/setup) 61 | 62 | ## License 63 | 64 | This project is licensed under the Apache 2.0 License 65 | -------------------------------------------------------------------------------- /v2/sunshine/notely_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/assets/logo.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | Notely_smallCreated with Sketch. -------------------------------------------------------------------------------- /v2/sunshine/notely_app/assets/ticket_sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /v2/sunshine/notely_app/assets/user_sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 19 | 20 | 21 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/download.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/install.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/load-unsafe-scripts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/load-unsafe-scripts.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/manage-apps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/manage-apps.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/screenshot.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/security.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/security.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/upload.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/images/url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_app/images/url.png -------------------------------------------------------------------------------- /v2/sunshine/notely_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Notely", 3 | "author": { 4 | "name": "octillery", 5 | "email": "octillery@zendesk.com", 6 | "url": "https://www.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": false, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": "assets/ticket_sidebar.html", 13 | "user_sidebar": "assets/user_sidebar.html" 14 | } 15 | }, 16 | "version": "1.0", 17 | "frameworkVersion": "2.0" 18 | } 19 | -------------------------------------------------------------------------------- /v2/sunshine/notely_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Notely", 4 | "short_description": "App to record notes of various types against a user", 5 | "long_description": "App to record notes of various types against a user \n as an event that shows up in the \n customer context interaction history.", 6 | "installation_instructions": "Simply click install." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/README.md: -------------------------------------------------------------------------------- 1 | # Notely Timeline 2 | 3 | View a timeline of user notes with the ability to filter by note type. 4 | 5 | ### Screenshot(s): 6 | ![screenshot](images/screenshot.png) 7 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_timeline_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_timeline_app/assets/logo.png -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/assets/ticket_sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 29 | 30 | 31 | 32 | 40 | 41 |
42 |
43 |
44 | 45 | 46 | 47 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/assets/user_sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 29 | 30 | 31 | 32 | 40 | 41 |
42 |
43 |
44 | 45 | 46 | 47 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/images/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/notely_timeline_app/images/screenshot.png -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Notely Timeline", 3 | "author": { 4 | "name": "octillery", 5 | "email": "jalviso@zendesk.com", 6 | "url": "https://www.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": false, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": "assets/ticket_sidebar.html", 13 | "user_sidebar": "assets/user_sidebar.html" 14 | } 15 | }, 16 | "version": "1.0", 17 | "frameworkVersion": "2.0" 18 | } 19 | -------------------------------------------------------------------------------- /v2/sunshine/notely_timeline_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Notely Timeline", 4 | "short_description": "App to view all recorded Notely notes about a user.", 5 | "long_description": "App to view all recorded Notely notes \n about a user in a single location with \n the ability to sort by note type.", 6 | "installation_instructions": "Simply click install." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/README.md: -------------------------------------------------------------------------------- 1 | # User Profiles 2 | 3 | Zendesk Support sidebar app. Displays all of the profiles for a given user from the Sunshine profiles service. 4 | 5 | ### The following information is displayed: 6 | 7 | * User's name and avatar 8 | * User profiles grouped by source and type 9 | * Attributes for each profile 10 | * Supports nested objects and arrays of primitive types 11 | 12 | Please submit bug reports to [the ICARUS JIRA board](https://zendesk.atlassian.net/jira/software/projects/ICARUS/boards/1415). Pull requests are welcome. 13 | 14 | ### Screenshot(s): 15 | ![Screen Shot 2019-03-25 at 1 51 24 PM](https://user-images.githubusercontent.com/4695062/54953336-3ab6cc80-4f05-11e9-8233-2d0c0c6f3cb5.png) 16 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 19 | 20 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/user_profiles_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/sunshine/user_profiles_app/assets/logo.png -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | profiles-app-icon 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/assets/styles.css: -------------------------------------------------------------------------------- 1 | .avatar-img { 2 | width: 60px; 3 | height: 60px; 4 | border-radius: 50%; 5 | background-repeat: no-repeat; 6 | background-position: center; 7 | background-size: cover; 8 | margin: 16px auto 0 auto; 9 | } 10 | 11 | .requester-name { 12 | margin: 8px 0; 13 | } 14 | 15 | .vertical-line { 16 | width: 50%; 17 | height: 16px; 18 | border-right: 1px solid #D8DCDE; 19 | } 20 | 21 | .profile { 22 | padding: 8px 12px; 23 | border: 1px solid #D8DCDE; 24 | border-radius: 4px; 25 | } 26 | 27 | .profile:last-of-type { 28 | margin-bottom: 16px; 29 | } 30 | 31 | 32 | .profile-header { 33 | } 34 | 35 | .profile-attribute { 36 | display: flex; 37 | flex-wrap: wrap; 38 | } 39 | 40 | .profile-key { 41 | flex: 1; 42 | word-wrap: break-word; 43 | color: #87929D; 44 | } 45 | 46 | .profile-value { 47 | flex: 1; 48 | word-wrap: break-word; 49 | } 50 | 51 | .list-item { 52 | margin-right: 4px; 53 | margin-bottom: 2px; 54 | } 55 | 56 | .no-data { 57 | color: #87929D; 58 | font-style: italic; 59 | } 60 | 61 | .bottom-blur { 62 | position: fixed; 63 | bottom: 0; 64 | left: 0; 65 | width: 100%; 66 | height: 20px; 67 | box-shadow: inset 0px -16px 10px -10px rgba(255,255,255,1); 68 | } 69 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "User Profiles", 3 | "author": { 4 | "name": "Jeff", 5 | "email": "jklein@zendesk.com", 6 | "url": "" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": "assets/index.html" 13 | } 14 | }, 15 | "version": "1.0", 16 | "frameworkVersion": "2.0" 17 | } 18 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/node_modules/.yarn-integrity: -------------------------------------------------------------------------------- 1 | { 2 | "systemParams": "darwin-x64-67", 3 | "modulesFolders": [], 4 | "flags": [], 5 | "linkedModules": [], 6 | "topLevelPatterns": [], 7 | "lockfileEntries": {}, 8 | "files": [], 9 | "artifacts": {} 10 | } -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Zen Tunes", 4 | "short_description": "Play the famous zen tunes in your help desk.", 5 | "long_description": "Play the famous zen tunes in your help desk and \n listen to the beats it has to offer.", 6 | "installation_instructions": "Simply click install." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/sunshine/user_profiles_app/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | -------------------------------------------------------------------------------- /v2/support/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Support Sample Apps 4 | 5 | This repository provides you with sample Apps to help learn how to use the Zendesk Apps framework v2 and Zendesk Support APIs. 6 | -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ADDITIONAL TERMS AND CONDITIONS 16 | 17 | Capitalized terms used herein have the meaning set forth in the 18 | Zendesk, Inc. (“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) 19 | (the “Terms”). The software made available herein constitutes the source code for a 20 | Zendesk Application (“Application Software”) which may be implemented to 21 | enable features or functionality to be utilized in connection with a subscription 22 | to the Service. Notwithstanding anything to the contrary set forth in the Terms 23 | or any other agreement by and between you and Zendesk, Application Software is 24 | provided “AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty 25 | as to the Application Software. ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND THOSE ARISING FROM A COURSE 28 | OF DEALING OR USAGE OF TRADE RELATED TO THE APPLICATION SOFTWARE, ITS USE OR ANY INABILITY 29 | TO USE IT OR THE RESULTS OF ITS USE. 30 | 31 | Zendesk makes Zendesk Applications available for use through the user interface of 32 | the Service in the manner described (for each Zendesk Application) at www.zendesk.com/apps 33 | (“Service Implementation”). Use of Application Software, other than in connection with a 34 | Service Implementation is subject to the following risks and conditions: (i) the Application 35 | Software may contain errors, design flaws or other problems; and (ii) use of the Application 36 | Software may result in unexpected results, loss of data, project delays or other unpredictable 37 | damage or loss. Zendesk only supports the Application Software currently available and installed 38 | through the Service Implementation. By utilizing Application Software other than in connection 39 | with the Service Implementation, you are agreeing that Zendesk shall have no obligation to 40 | correct any bugs, defects or errors in the Application Software you have utilized or 41 | otherwise to support or maintain the Application Software you have utilized. 42 | 43 | If you elect to utilize any Application Software other than through a Service Implementation, 44 | you are agreeing to release Zendesk from any claim with regard to the Application Software, 45 | its operation, availability or its failure to operate or be available. 46 | Without limiting the generality of the foregoing, You acknowledge and agree that neither the use, 47 | availability nor operation of any Application Software shall be subject to any service level 48 | commitment applicable to the Service. 49 | -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Basic Ticket Sample App 4 | 5 | This sample app displays a message noting changes made by the current user. 6 | 7 | ### Screenshot(s): 8 | ![screen shot 2016-10-31 at 2 12 42 pm](https://cloud.githubusercontent.com/assets/2517811/19843218/3fa9689e-9f74-11e6-9ed2-2d0ffe408b46.png) 9 | -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/assets/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
Loading...
7 | 8 | 9 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/basic_ticket_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/basic_ticket_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Basic Ticket Sample App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://help.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": { 13 | "url": "assets/iframe.html", 14 | "flexible": true 15 | } 16 | } 17 | }, 18 | "version": "1.0", 19 | "frameworkVersion": "2.0" 20 | } 21 | -------------------------------------------------------------------------------- /v2/support/basic_ticket_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "short_description": "Demo Ticket Sidebar app.", 4 | "long_description": "Demo Ticket Sidebar app.", 5 | "installation_instructions": "Find the Demo Ticket Sidebar app in the Zendesk marketplace.", 6 | "name": "Basic Ticket Sample App" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/garden_sample_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ADDITIONAL TERMS AND CONDITIONS 16 | 17 | Capitalized terms used herein have the meaning set forth in the 18 | Zendesk, Inc. (“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) 19 | (the “Terms”). The software made available herein constitutes the source code for a 20 | Zendesk Application (“Application Software”) which may be implemented to 21 | enable features or functionality to be utilized in connection with a subscription 22 | to the Service. Notwithstanding anything to the contrary set forth in the Terms 23 | or any other agreement by and between you and Zendesk, Application Software is 24 | provided “AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty 25 | as to the Application Software. ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND THOSE ARISING FROM A COURSE 28 | OF DEALING OR USAGE OF TRADE RELATED TO THE APPLICATION SOFTWARE, ITS USE OR ANY INABILITY 29 | TO USE IT OR THE RESULTS OF ITS USE. 30 | 31 | Zendesk makes Zendesk Applications available for use through the user interface of 32 | the Service in the manner described (for each Zendesk Application) at www.zendesk.com/apps 33 | (“Service Implementation”). Use of Application Software, other than in connection with a 34 | Service Implementation is subject to the following risks and conditions: (i) the Application 35 | Software may contain errors, design flaws or other problems; and (ii) use of the Application 36 | Software may result in unexpected results, loss of data, project delays or other unpredictable 37 | damage or loss. Zendesk only supports the Application Software currently available and installed 38 | through the Service Implementation. By utilizing Application Software other than in connection 39 | with the Service Implementation, you are agreeing that Zendesk shall have no obligation to 40 | correct any bugs, defects or errors in the Application Software you have utilized or 41 | otherwise to support or maintain the Application Software you have utilized. 42 | 43 | If you elect to utilize any Application Software other than through a Service Implementation, 44 | you are agreeing to release Zendesk from any claim with regard to the Application Software, 45 | its operation, availability or its failure to operate or be available. 46 | Without limiting the generality of the foregoing, You acknowledge and agree that neither the use, 47 | availability nor operation of any Application Software shall be subject to any service level 48 | commitment applicable to the Service. 49 | -------------------------------------------------------------------------------- /v2/support/garden_sample_app/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Garden Sample App 4 | 5 | This sample app demonstrates a selection of styles possible using Zendesk Garden bootstrap styles. 6 | 7 | ### Screenshot: 8 | ![Garden Sample App screenshot](https://user-images.githubusercontent.com/143773/43234970-dc9cb758-9033-11e8-856e-2194db52cce0.png) 9 | -------------------------------------------------------------------------------- /v2/support/garden_sample_app/assets/icon_nav_bar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /v2/support/garden_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/garden_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/garden_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/garden_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/garden_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /v2/support/garden_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Garden Sample App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://help.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "nav_bar": "assets/iframe.html" 13 | } 14 | }, 15 | "version": "1.0", 16 | "frameworkVersion": "2.0" 17 | } 18 | -------------------------------------------------------------------------------- /v2/support/garden_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "long_description": "Demo app showing Zendesk Garden styles", 4 | "installation_instructions": "Find the app in the Zendesk marketplace.", 5 | "short_description": "Demo app showing Zendesk Garden styles", 6 | "name": "Garden Sample App" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/instances_sample_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ADDITIONAL TERMS AND CONDITIONS 16 | 17 | Capitalized terms used herein have the meaning set forth in the 18 | Zendesk, Inc. (“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) 19 | (the “Terms”). The software made available herein constitutes the source code for a 20 | Zendesk Application (“Application Software”) which may be implemented to 21 | enable features or functionality to be utilized in connection with a subscription 22 | to the Service. Notwithstanding anything to the contrary set forth in the Terms 23 | or any other agreement by and between you and Zendesk, Application Software is 24 | provided “AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty 25 | as to the Application Software. ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND THOSE ARISING FROM A COURSE 28 | OF DEALING OR USAGE OF TRADE RELATED TO THE APPLICATION SOFTWARE, ITS USE OR ANY INABILITY 29 | TO USE IT OR THE RESULTS OF ITS USE. 30 | 31 | Zendesk makes Zendesk Applications available for use through the user interface of 32 | the Service in the manner described (for each Zendesk Application) at www.zendesk.com/apps 33 | (“Service Implementation”). Use of Application Software, other than in connection with a 34 | Service Implementation is subject to the following risks and conditions: (i) the Application 35 | Software may contain errors, design flaws or other problems; and (ii) use of the Application 36 | Software may result in unexpected results, loss of data, project delays or other unpredictable 37 | damage or loss. Zendesk only supports the Application Software currently available and installed 38 | through the Service Implementation. By utilizing Application Software other than in connection 39 | with the Service Implementation, you are agreeing that Zendesk shall have no obligation to 40 | correct any bugs, defects or errors in the Application Software you have utilized or 41 | otherwise to support or maintain the Application Software you have utilized. 42 | 43 | If you elect to utilize any Application Software other than through a Service Implementation, 44 | you are agreeing to release Zendesk from any claim with regard to the Application Software, 45 | its operation, availability or its failure to operate or be available. 46 | Without limiting the generality of the foregoing, You acknowledge and agree that neither the use, 47 | availability nor operation of any Application Software shall be subject to any service level 48 | commitment applicable to the Service. 49 | -------------------------------------------------------------------------------- /v2/support/instances_sample_app/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | # Instances API Sample App 4 | 5 | This sample app uses the [Instances API](https://developer.zendesk.com/apps/docs/apps-v2/api_reference#client.instanceguid) to add a template comment from the background location when the comment box is empty. It also uses the `{ autoLoad: false }` location option to avoid rendering the iframe in the ticket_sidebar location. 6 | 7 | ### Screenshot(s): 8 | ![instances](https://cloud.githubusercontent.com/assets/2517811/20699141/d5ee4ac6-b659-11e6-9375-f8b376a5f712.png) 9 | -------------------------------------------------------------------------------- /v2/support/instances_sample_app/assets/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /v2/support/instances_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/instances_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/instances_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/instances_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/instances_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/support/instances_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Instances API Sample App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://help.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "background": "assets/iframe.html", 13 | "ticket_sidebar": { 14 | "autoLoad": false, 15 | "flexible": true 16 | } 17 | } 18 | }, 19 | "version": "1.0", 20 | "frameworkVersion": "2.0" 21 | } 22 | -------------------------------------------------------------------------------- /v2/support/instances_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "long_description": "Demo Instances API app.", 4 | "installation_instructions": "Find the app in the Zendesk marketplace.", 5 | "short_description": "Demo Instances API app.", 6 | "name": "Instances API Sample App" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2016 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ADDITIONAL TERMS AND CONDITIONS 16 | 17 | Capitalized terms used herein have the meaning set forth in the 18 | Zendesk, Inc. (“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) 19 | (the “Terms”). The software made available herein constitutes the source code for a 20 | Zendesk Application (“Application Software”) which may be implemented to 21 | enable features or functionality to be utilized in connection with a subscription 22 | to the Service. Notwithstanding anything to the contrary set forth in the Terms 23 | or any other agreement by and between you and Zendesk, Application Software is 24 | provided “AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty 25 | as to the Application Software. ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND THOSE ARISING FROM A COURSE 28 | OF DEALING OR USAGE OF TRADE RELATED TO THE APPLICATION SOFTWARE, ITS USE OR ANY INABILITY 29 | TO USE IT OR THE RESULTS OF ITS USE. 30 | 31 | Zendesk makes Zendesk Applications available for use through the user interface of 32 | the Service in the manner described (for each Zendesk Application) at www.zendesk.com/apps 33 | (“Service Implementation”). Use of Application Software, other than in connection with a 34 | Service Implementation is subject to the following risks and conditions: (i) the Application 35 | Software may contain errors, design flaws or other problems; and (ii) use of the Application 36 | Software may result in unexpected results, loss of data, project delays or other unpredictable 37 | damage or loss. Zendesk only supports the Application Software currently available and installed 38 | through the Service Implementation. By utilizing Application Software other than in connection 39 | with the Service Implementation, you are agreeing that Zendesk shall have no obligation to 40 | correct any bugs, defects or errors in the Application Software you have utilized or 41 | otherwise to support or maintain the Application Software you have utilized. 42 | 43 | If you elect to utilize any Application Software other than through a Service Implementation, 44 | you are agreeing to release Zendesk from any claim with regard to the Application Software, 45 | its operation, availability or its failure to operate or be available. 46 | Without limiting the generality of the foregoing, You acknowledge and agree that neither the use, 47 | availability nor operation of any Application Software shall be subject to any service level 48 | commitment applicable to the Service. 49 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | # Modal Sample App 4 | 5 | This sample app displays text on the ticket sidebar with an edit button. The edit button opens a modal where you can edit the text displayed. The text is saved on local storage. 6 | 7 | ### Screenshot(s): 8 | ![modal](https://cloud.githubusercontent.com/assets/2517811/19846439/5fa95d60-9f93-11e6-9559-3e2155e3990b.gif) 9 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/assets/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Loading...
8 | 9 | 10 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/modal_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/modal_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/modal_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/modal_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/assets/styles.css: -------------------------------------------------------------------------------- 1 | #modal textarea { 2 | width: 100%; 3 | height: 100px; 4 | } 5 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Modal Sample App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://help.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": { 13 | "url": "assets/iframe.html", 14 | "flexible": true 15 | } 16 | } 17 | }, 18 | "version": "1.0", 19 | "frameworkVersion": "2.0" 20 | } 21 | -------------------------------------------------------------------------------- /v2/support/modal_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "installation_instructions": "Find the app in the Zendesk marketplace.", 4 | "long_description": "Demo Modal app.", 5 | "short_description": "Demo Modal app.", 6 | "name": "Basic Modal Sample App" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/README.md: -------------------------------------------------------------------------------- 1 | # My Cat App 2 | 3 | A Zendesk app for cat lovers that allows you to share humorous pictures of cats with your favourite customers. 4 | 5 | Similar to the [Secure Settings Example App](https://github.com/zendesk/demo_apps/tree/master/v2/support/secure_settings_sample_app), this app leverages the secure settings functionality of Zendesk's App Framework to store an API token which is required for making requests to [The Cat API](https://thecatapi.com/). You can sign up for a for a free token [here](https://thecatapi.com/signup). 6 | 7 | Upon installation, the account admin will need to enter this key in the api_token parameter. -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/assets/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 |
16 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/my_cat_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/my_cat_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/assets/main.js: -------------------------------------------------------------------------------- 1 | const client = ZAFClient.init(); 2 | 3 | const settings = { 4 | url: 'https://api.thecatapi.com/v1/images/search?format=json', 5 | headers: {"x-api-key": "{{setting.api_token}}"}, 6 | secure: true, 7 | type: 'GET', 8 | contentType: 'application/json' 9 | }; 10 | 11 | const newCatButton = document.getElementById('new-cat-button') 12 | 13 | const sendCatButton = document.getElementById('send-cat-button') 14 | 15 | const renderImage = (catPictureLink) => { 16 | const catPictureElement = document.querySelector("img[id='cat-picture']"); 17 | catPictureElement.src = catPictureLink; 18 | } 19 | 20 | const fetchNewCat = () => { 21 | client.request(settings).then(function (data) { 22 | const catImageLink = data['0']['url']; 23 | renderImage(catImageLink); 24 | }); 25 | } 26 | 27 | const attachCatToTicketComment = () => { 28 | const catImageSource = document.querySelector("img[id='cat-picture']").src; 29 | client.invoke('comment.appendHtml', ``) 30 | } 31 | 32 | client.on('app.registered', function () { 33 | fetchNewCat(); 34 | }); 35 | 36 | newCatButton.addEventListener('click', fetchNewCat); 37 | 38 | sendCatButton.addEventListener('click', attachCatToTicketComment); 39 | -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/assets/styles.css: -------------------------------------------------------------------------------- 1 | main { 2 | align-items: center; 3 | justify-content: center; 4 | display: flex; 5 | flex-direction: column; 6 | } 7 | 8 | #cat-picture { 9 | margin: 2em 0em 2em 0em; 10 | } 11 | 12 | .c-btn { 13 | margin: 0.5em; 14 | } 15 | -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "My Cat App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://support.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": { 13 | "url": "assets/iframe.html", 14 | "flexible": true, 15 | "size": { 16 | "height": "375px" 17 | } 18 | } 19 | } 20 | }, 21 | "domainWhitelist": ["thecatapi.com", "api.thecatapi.com"], 22 | "parameters": [ 23 | { 24 | "name": "api_token", 25 | "type": "text", 26 | "secure": true 27 | } 28 | ], 29 | "version": "1.0", 30 | "frameworkVersion": "2.0" 31 | } 32 | -------------------------------------------------------------------------------- /v2/support/my_cat_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "My Cat App", 4 | "short_description": "An app for cat lovers", 5 | "long_description": "An app to share humorous pictures of cats with your favourite customers", 6 | "installation_instructions": "You'll just need to add an API token for The Cat API which you can get for free from [here](https://thecatapi.com/signup)" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ADDITIONAL TERMS AND CONDITIONS 16 | 17 | Capitalized terms used herein have the meaning set forth in the 18 | Zendesk, Inc. (“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) 19 | (the “Terms”). The software made available herein constitutes the source code for a 20 | Zendesk Application (“Application Software”) which may be implemented to 21 | enable features or functionality to be utilized in connection with a subscription 22 | to the Service. Notwithstanding anything to the contrary set forth in the Terms 23 | or any other agreement by and between you and Zendesk, Application Software is 24 | provided “AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty 25 | as to the Application Software. ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND THOSE ARISING FROM A COURSE 28 | OF DEALING OR USAGE OF TRADE RELATED TO THE APPLICATION SOFTWARE, ITS USE OR ANY INABILITY 29 | TO USE IT OR THE RESULTS OF ITS USE. 30 | 31 | Zendesk makes Zendesk Applications available for use through the user interface of 32 | the Service in the manner described (for each Zendesk Application) at www.zendesk.com/apps 33 | (“Service Implementation”). Use of Application Software, other than in connection with a 34 | Service Implementation is subject to the following risks and conditions: (i) the Application 35 | Software may contain errors, design flaws or other problems; and (ii) use of the Application 36 | Software may result in unexpected results, loss of data, project delays or other unpredictable 37 | damage or loss. Zendesk only supports the Application Software currently available and installed 38 | through the Service Implementation. By utilizing Application Software other than in connection 39 | with the Service Implementation, you are agreeing that Zendesk shall have no obligation to 40 | correct any bugs, defects or errors in the Application Software you have utilized or 41 | otherwise to support or maintain the Application Software you have utilized. 42 | 43 | If you elect to utilize any Application Software other than through a Service Implementation, 44 | you are agreeing to release Zendesk from any claim with regard to the Application Software, 45 | its operation, availability or its failure to operate or be available. 46 | Without limiting the generality of the foregoing, You acknowledge and agree that neither the use, 47 | availability nor operation of any Application Software shall be subject to any service level 48 | commitment applicable to the Service. 49 | -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | # Requirements Only Sample App 4 | 5 | This sample app shows to the developers how to add Apps requirements to their Apps. "Apps Requirements" are a neat feature that allows your App to install business rules, ticket fields, and all other resources that it might need to function properly. 6 | 7 | This App will only add requirements. It has no other logic or features. 8 | 9 | For an App that contains both please see [Requirements Sample App](./../requirements_sample_app) 10 | 11 | **Note:** Requirements aren't installed when running the app locally on the ZAT server. However, for testing purposes, you can install the app as a private app and then use the zat update command to make updates to the installed app. See [Updating an installed app](https://developer.zendesk.com/apps/docs/apps-v2/using_sdk#updating-an-installed-app). 12 | 13 | ### The following information is displayed: 14 | 15 | * Create Apps requirements 16 | 17 | Please submit bug reports to [Zendesk Support](https://support.zendesk.com/hc). Pull requests are welcome. 18 | 19 | ### Screenshot(s): 20 | 21 | N/A 22 | -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/requirements_only_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/requirements_only_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Requirements Only Sample App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com" 6 | }, 7 | "defaultLocale": "en", 8 | "private": true, 9 | "version": "1.0", 10 | "requirementsOnly": true 11 | } 12 | -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/requirements.json: -------------------------------------------------------------------------------- 1 | { 2 | "targets": { 3 | "a_basecamp_target": { 4 | "title": "A sample Target", 5 | "type": "basecamp_target", 6 | "target_url": "http://mytarget.com", 7 | "token": "123456", 8 | "project_id": "99999", 9 | "resource": "todo" 10 | }, 11 | "an_email_target": { 12 | "title": "A sample email Target", 13 | "type": "email_target", 14 | "email": "foo@bar.com", 15 | "subject": "Hello, from this target!" 16 | }, 17 | "url_target_v2":{ 18 | "type": "url_target", 19 | "title": "Test JSON to requestbin", 20 | "method": "post", 21 | "content_type": "application/json", 22 | "target_url": "http://requestb.in/13ualp61", 23 | "attribute": "message_value" 24 | } 25 | }, 26 | 27 | "ticket_fields": { 28 | "support_description": { 29 | "type": "text", 30 | "title": "Support description" 31 | }, 32 | 33 | "number_of_issues": { 34 | "type": "integer", 35 | "title": "Number of issues" 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /v2/support/requirements_only_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "installation_instructions": "Find the app in the Zendesk marketplace.", 4 | "long_description": "Requirements only app.", 5 | "short_description": "Requirements only app.", 6 | "name": "Requirements Only App" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 Zendesk 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | 15 | ADDITIONAL TERMS AND CONDITIONS 16 | 17 | Capitalized terms used herein have the meaning set forth in the 18 | Zendesk, Inc. (“Zendesk”) Terms of Service (available at www.zendesk.com/company/terms) 19 | (the “Terms”). The software made available herein constitutes the source code for a 20 | Zendesk Application (“Application Software”) which may be implemented to 21 | enable features or functionality to be utilized in connection with a subscription 22 | to the Service. Notwithstanding anything to the contrary set forth in the Terms 23 | or any other agreement by and between you and Zendesk, Application Software is 24 | provided “AS IS” and on an “AS AVAILABLE” basis, and that Zendesk makes no warranty 25 | as to the Application Software. ZENDESK DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, 26 | INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT AND THOSE ARISING FROM A COURSE 28 | OF DEALING OR USAGE OF TRADE RELATED TO THE APPLICATION SOFTWARE, ITS USE OR ANY INABILITY 29 | TO USE IT OR THE RESULTS OF ITS USE. 30 | 31 | Zendesk makes Zendesk Applications available for use through the user interface of 32 | the Service in the manner described (for each Zendesk Application) at www.zendesk.com/apps 33 | (“Service Implementation”). Use of Application Software, other than in connection with a 34 | Service Implementation is subject to the following risks and conditions: (i) the Application 35 | Software may contain errors, design flaws or other problems; and (ii) use of the Application 36 | Software may result in unexpected results, loss of data, project delays or other unpredictable 37 | damage or loss. Zendesk only supports the Application Software currently available and installed 38 | through the Service Implementation. By utilizing Application Software other than in connection 39 | with the Service Implementation, you are agreeing that Zendesk shall have no obligation to 40 | correct any bugs, defects or errors in the Application Software you have utilized or 41 | otherwise to support or maintain the Application Software you have utilized. 42 | 43 | If you elect to utilize any Application Software other than through a Service Implementation, 44 | you are agreeing to release Zendesk from any claim with regard to the Application Software, 45 | its operation, availability or its failure to operate or be available. 46 | Without limiting the generality of the foregoing, You acknowledge and agree that neither the use, 47 | availability nor operation of any Application Software shall be subject to any service level 48 | commitment applicable to the Service. 49 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | # Requirements Sample App 4 | 5 | This sample app shows to the developers how to add Apps requirements to their Apps. "Apps Requirements" are a neat feature that allows your App to install business rules, ticket fields, and all other resources that it might need to function properly. 6 | 7 | This App will add requirements as well as "reference" those requirements from within the App. 8 | 9 | For an App that only creates requirements and nothing else please see [Requirements Only Sample App](./../requirements_only_sample_app) 10 | 11 | **Notes:** 12 | - Requirements aren't installed when running the app locally on the ZAT server. However, for testing purposes, you can install the app as a private app and then use the zat update command to make updates to the installed app. See [Updating an installed app](https://developer.zendesk.com/apps/docs/apps-v2/using_sdk#updating-an-installed-app). 13 | - If you have multiple ticket forms you will need to manually add the ticket field created by this app to one of the forms. 14 | 15 | ### The following information is displayed: 16 | 17 | * Create Apps requirements 18 | 19 | Please submit bug reports to [Zendesk Support](https://support.zendesk.com/hc). Pull requests are welcome. 20 | 21 | ### Screenshot(s): 22 | 23 | ![screen shot 2017-03-22 at 4 11 38 pm](https://cloud.githubusercontent.com/assets/2517811/24183112/4a792906-0f1a-11e7-8a49-464e85fdd321.png) 24 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/assets/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
Loading...
7 | 8 | 9 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/requirements_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/requirements_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Requirements Sample App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com" 6 | }, 7 | "defaultLocale": "en", 8 | "private": true, 9 | "version": "1.0", 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": { 13 | "url": "assets/iframe.html", 14 | "flexible": true 15 | }, 16 | "new_ticket_sidebar": { 17 | "url":"assets/iframe.html", 18 | "flexible": true 19 | } 20 | } 21 | }, 22 | "frameworkVersion": "2.0" 23 | } 24 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/requirements.json: -------------------------------------------------------------------------------- 1 | { 2 | "ticket_fields": { 3 | "ticket_custom_field": { 4 | "type": "text", 5 | "title": "Sample app ticket field" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/requirements_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "installation_instructions": "Find the app in the Zendesk marketplace.", 4 | "long_description": "Requirements sample app.", 5 | "short_description": "Requirements sample app.", 6 | "name": "Requirements Sample App" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/README.md: -------------------------------------------------------------------------------- 1 | # Secure Settings Example App 2 | 3 | This sample app shows how to add Secure Settings to an app. "Secure Settings" is a neat feature that allows your App to pass a secure setting via the proxy that is invisible to normal agents. Detailed documentation regarding this feature can be found here: https://developer.zendesk.com/apps/docs/developer-guide/using_sdk#using-secure-settings . 4 | 5 | In particular, this App uses a secure setting to store a token for https://thecatapi.com/ which is required for making api requests. To get such a key, you will need to sign up for an account, and then grab your api key from the signup email. 6 | 7 | On installation the account admin should paste this key into the "catering_token" field. 8 | 9 | The app will parse a single response from thecatapi and render it as an image within the app's iframe. The request made is a GET request to /images/search per https://documenter.getpostman.com/view/4016432/RWToRJCq . 10 | 11 | In particular, it will make this request: 12 | 13 | curl --request GET \ 14 | --url 'https://api.thecatapi.com/v1/images/search?format=json' \ 15 | --header 'Content-Type: application/json' \ 16 | --header 'x-api-key: {{catering_token}}' 17 | 18 | ### Screenshot(s): 19 | 20 | None as yet! 21 | -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/assets/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
Adopt a new cat
11 | 12 | 13 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/secure_settings_sample_app/assets/logo-small.png -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/support/secure_settings_sample_app/assets/logo.png -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/assets/styles.css: -------------------------------------------------------------------------------- 1 | div.button { 2 | color: yellow; 3 | background-color: blue; 4 | border-style: solid; 5 | border-width: 2px; 6 | } 7 | -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Secure Settings Example App", 3 | "author": { 4 | "name": "Zendesk", 5 | "email": "support@zendesk.com", 6 | "url": "https://support.zendesk.com" 7 | }, 8 | "defaultLocale": "en", 9 | "private": true, 10 | "location": { 11 | "support": { 12 | "ticket_sidebar": { 13 | "url": "assets/iframe.html", 14 | "flexible": true 15 | } 16 | } 17 | }, 18 | "domainWhitelist": ["thecatapi.com", "api.thecatapi.com"], 19 | "parameters": [ 20 | { 21 | "name": "api_token", 22 | "type": "text", 23 | "secure": true 24 | } 25 | ], 26 | "version": "1.0", 27 | "frameworkVersion": "2.0" 28 | } 29 | -------------------------------------------------------------------------------- /v2/support/secure_settings_sample_app/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "Bag end catering helper", 4 | "short_description": "Sugar and spice and all things nice", 5 | "long_description": "Bagginses and Boffins, Tooks and Brandybucks, Grubbs, Chubbs, Hornblowers, Bolgers, Bracegirdles and Proudfoots.", 6 | "installation_instructions": "Hold your breath, try not to sneeze. Catering, now that's a right wheeze. Find a tomato and give it a good squeeze. Place your friends and compatriots at their ease. Finally, spin right round baby right round like a record baby right round round round. Then click the install button." 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/README.md: -------------------------------------------------------------------------------- 1 | :warning: *Use of this software is subject to important terms and conditions as set forth in the License file* :warning: 2 | 3 | ## Zendesk Integration Services Sample apps 4 | 5 | This repository provides you with sample Apps to help learn how to use the Zendesk Apps framework v2 and Zendesk Integration Services. 6 | 7 | Please visit the [Zendesk Developer portal](https://developer.zendesk.com/documentation/integration-services/) for more documentations. 8 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | .zat 3 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/README.md: -------------------------------------------------------------------------------- 1 | # ZIS Tutorial - Zendesk App as an admin interface 2 | 3 | This folder contains the source code for [Part 1: Building an app with OAuth](https://developer.zendesk.com/documentation/integration-services/zis-tutorials/zendesk-app-admin-interface/app-oauth/) 4 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/bootstrap.js: -------------------------------------------------------------------------------- 1 | // Bootstrap the app when DOM is ready 2 | $(function() { 3 | // Initialise the Zendesk JavaScript API client 4 | // https://developer.zendesk.com/apps/docs/developer-guide/getting_started 5 | window.client = ZAFClient.init(); 6 | 7 | // Subdomain is required to kick-off OAuth flow. See: connect.js 8 | let subdomain = undefined; 9 | 10 | // Integration key is the unique identifier for your integration app 11 | let integrationKey = undefined; 12 | 13 | client.context().then(function(context) { 14 | // Derive subdomain & integration key 15 | subdomain = context['account']['subdomain'] 16 | integrationKey = subdomain + "_zis_tutorial" 17 | console.log("Integration key: " + integrationKey); 18 | }).then(function() { 19 | // Bind button to start OAuth flow 20 | $("#btnConnect").click(function() { startOAuth(integrationKey, subdomain) }); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/connect.js: -------------------------------------------------------------------------------- 1 | // zendeskConnectionName is a human-friendly name for referencing 2 | // Zendesk OAuth connection stored in ZIS 3 | const zendeskConnectionName = "zendesk"; 4 | 5 | // zendeskOAuthClientName is used to reference the companion Zendesk OAuth 6 | // client that came with the ZIS integration 7 | const zendeskOAuthClientName = "zendesk"; 8 | 9 | function startOAuth(integrationKey, subdomain) { 10 | let data = JSON.stringify({ 11 | name: zendeskConnectionName, 12 | oauth_client_name: zendeskOAuthClientName, 13 | oauth_url_subdomain: subdomain, 14 | origin_oauth_redirect_url: window.location.href, 15 | permission_scopes: "read write" 16 | }); 17 | 18 | let request = { 19 | type: "POST", 20 | url: "/api/services/zis/connections/oauth/start/" + integrationKey, 21 | contentType: "application/json", 22 | data: data 23 | }; 24 | 25 | client.request(request).then( 26 | function(response) { 27 | console.log("OAuth started successfully"); 28 | authorize(response.redirect_url) 29 | }, 30 | function(response) { 31 | console.log("Failed to start OAuth: ", response); 32 | } 33 | ); 34 | }; 35 | 36 | function authorize(redirectURL) { 37 | let authWindow = window.open(redirectURL, '_blank') 38 | setTimeout(watchToken, 1500); 39 | // poll token from the newly opened window 40 | function watchToken() { 41 | try { 42 | let params = new URL(authWindow.location.href).searchParams; 43 | // Cross-origin access will cause error on the above line 44 | // Once the oauth is completed, the authWindow's location 45 | // will be redirected back to the same origin, which in turn 46 | // allow us to get the verification token 47 | let verificationToken = params.get('verification_token'); 48 | console.log("Successfully established connection: " + zendeskConnectionName); 49 | authWindow.close(); 50 | } catch(err) { 51 | console.log("DOM error is expected during cross domain authorization: " + err); 52 | setTimeout(watchToken, 500) 53 | } 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 |
25 |
26 |
27 |
28 | 29 |
30 |
31 |
32 |
33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/logo-small.png -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/logo.png -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ZIS Tutorial - Slack Notifier", 3 | "author": { 4 | "name": "My name", 5 | "email": "dev@example.com", 6 | "url": "https://www.example.com" 7 | }, 8 | "version": "1.0", 9 | "frameworkVersion": "2.0", 10 | "defaultLocale": "en", 11 | "private": true, 12 | "location": { 13 | "support": { 14 | "nav_bar": "assets/index.html" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_1/src/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "ZIS Tutorial - Slack Notifier Part 1", 4 | "short_description": "An example app to show case Zendesk apps being used as an admin UI for Zendesk Integration Services", 5 | "long_description": "An example app to show case Zendesk apps being used as an admin UI for Zendesk Integration Services", 6 | "installation_instructions": "Follow the instruction to install as a private app: https://developer.zendesk.com/documentation/apps/getting-started/uploading-and-installing-a-private-app/" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | .zat 3 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/README.md: -------------------------------------------------------------------------------- 1 | # ZIS Tutorial - Zendesk App as an admin interface 2 | 3 | This folder contains the source code for [Part 3: Creating the configuration user interface](https://developer.zendesk.com/documentation/integration-services/zis-tutorials/zendesk-app-admin-interface/create-config-ui/) 4 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/bootstrap.js: -------------------------------------------------------------------------------- 1 | // Bootstrap the app when DOM is ready 2 | $(function() { 3 | // Initialise the Zendesk JavaScript API client 4 | // https://developer.zendesk.com/apps/docs/developer-guide/getting_started 5 | window.client = ZAFClient.init(); 6 | 7 | // Subdomain is required to kick-off OAuth flow. See: connect.js 8 | let subdomain = undefined; 9 | 10 | // Integration key is the unique identifier for your integration app 11 | let integrationKey = undefined; 12 | 13 | client.context().then(function(context) { 14 | // Derive subdomain & integration key 15 | subdomain = context['account']['subdomain'] 16 | integrationKey = subdomain + "_zis_tutorial" 17 | console.log("Integration key: " + integrationKey); 18 | }).then(function() { 19 | // Bind button to start OAuth flow 20 | $("#btnConnect").click(function() { startOAuth(integrationKey, subdomain) }); 21 | 22 | // Bind button to submit config 23 | $("#submit").click(function() { submitConfig(integrationKey) }); 24 | 25 | // Fetch configuration data and render on UI 26 | fetchConfig(integrationKey); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/config.js: -------------------------------------------------------------------------------- 1 | // configScope is a custom defined key for referencing the configuration data 2 | let configScope = "slackNotification"; 3 | 4 | // scopeExists is a boolean flag to indicate if the config data exists 5 | // for a given scope 6 | let scopeExists = false; 7 | 8 | // fetchConfig defines the function to fetch config data 9 | function fetchConfig(integrationKey) { 10 | // Fetch config request 11 | let request = { 12 | type: "GET", 13 | url: "/api/services/zis/integrations/" + integrationKey + 14 | "/configs?filter[scope]=" + configScope 15 | }; 16 | 17 | client.request(request).then( 18 | function(response) { 19 | console.log("Config fetched successfully: ", response.configs[0].config) 20 | scopeExists = true; 21 | updateComponents(response.configs[0].config); 22 | }, 23 | function(response) { 24 | console.log("Config fetching failed: ", response) 25 | if (response.status == 404) { 26 | scopeExists = false; 27 | } 28 | } 29 | ); 30 | } 31 | 32 | // submitConfig maps the data from DOM and submit through ZIS Configs API 33 | function submitConfig(integrationKey) { 34 | // Prepare the config payload 35 | let data = JSON.stringify({ 36 | scope: configScope, 37 | config: { 38 | priority: $("#select-priority").val(), 39 | channel: $("#txt-channel").val() 40 | } 41 | }); 42 | 43 | // The request is for create or update config data 44 | let request; 45 | 46 | if (scopeExists) { 47 | // request for update config 48 | request = { 49 | type: "PUT", 50 | url: "/api/services/zis/integrations/" + integrationKey + "/configs/" + configScope, 51 | contentType: "application/json", 52 | data: data 53 | }; 54 | } else { 55 | // request for create config 56 | request = { 57 | type: "POST", 58 | url: "/api/services/zis/integrations/" + integrationKey + "/configs", 59 | contentType: "application/json", 60 | data: data 61 | }; 62 | } 63 | 64 | client.request(request).then( 65 | function(response) { 66 | console.log("Config submitted successfully: ", response); 67 | client.invoke('notify', "Submitted successfully"); 68 | scopeExists = true; 69 | }, 70 | function(response) { 71 | console.log("Config submission failed: ", response); 72 | } 73 | ); 74 | } 75 | 76 | // updateComponents updates the UI components with the newly fetched config data 77 | function updateComponents(config) { 78 | console.log("Updating components with config: ", config); 79 | $("#select-priority").val(config.priority); 80 | $("#txt-channel").val(config.channel); 81 | } 82 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/connect.js: -------------------------------------------------------------------------------- 1 | // zendeskConnectionName is a human-friendly name for referencing 2 | // Zendesk OAuth connection stored in ZIS 3 | const zendeskConnectionName = "zendesk"; 4 | 5 | // zendeskOAuthClientName is used to reference the companion Zendesk OAuth 6 | // client that came with the ZIS integration 7 | const zendeskOAuthClientName = "zendesk"; 8 | 9 | function startOAuth(integrationKey, subdomain) { 10 | let data = JSON.stringify({ 11 | name: zendeskConnectionName, 12 | oauth_client_name: zendeskOAuthClientName, 13 | oauth_url_subdomain: subdomain, 14 | origin_oauth_redirect_url: window.location.href, 15 | permission_scopes: "read write" 16 | }); 17 | 18 | let request = { 19 | type: "POST", 20 | url: "/api/services/zis/connections/oauth/start/" + integrationKey, 21 | contentType: "application/json", 22 | data: data 23 | }; 24 | 25 | client.request(request).then( 26 | function(response) { 27 | console.log("OAuth started successfully"); 28 | authorize(response.redirect_url) 29 | }, 30 | function(response) { 31 | console.log("Failed to start OAuth: ", response); 32 | } 33 | ); 34 | }; 35 | 36 | function authorize(redirectURL) { 37 | let authWindow = window.open(redirectURL, '_blank') 38 | setTimeout(watchToken, 1500); 39 | // poll token from the newly opened window 40 | function watchToken() { 41 | try { 42 | let params = new URL(authWindow.location.href).searchParams; 43 | // Cross-origin access will cause error on the above line 44 | // Once the oauth is completed, the authWindow's location 45 | // will be redirected back to the same origin, which in turn 46 | // allow us to get the verification token 47 | let verificationToken = params.get('verification_token'); 48 | console.log("Successfully established connection: " + zendeskConnectionName); 49 | authWindow.close(); 50 | } catch(err) { 51 | console.log("DOM error is expected during cross domain authorization: " + err); 52 | setTimeout(watchToken, 500) 53 | } 54 | } 55 | }; 56 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 |
35 |
36 | 37 | 43 |
44 |
45 |
46 |
47 | 48 | 49 |
50 |
51 |
52 |
53 |
54 | 55 |
56 |
57 |
58 |
59 |
60 |
61 | 62 | 63 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/logo-small.png -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/logo.png -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ZIS Tutorial - Slack Notifier", 3 | "author": { 4 | "name": "My name", 5 | "email": "dev@example.com", 6 | "url": "https://www.example.com" 7 | }, 8 | "version": "1.0", 9 | "frameworkVersion": "2.0", 10 | "defaultLocale": "en", 11 | "private": true, 12 | "location": { 13 | "support": { 14 | "nav_bar": "assets/index.html" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_2/src/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "ZIS Tutorial - Slack Notifier Part 2", 4 | "short_description": "An example app to show case Zendesk apps being used as an admin UI for Zendesk Integration Services", 5 | "long_description": "An example app to show case Zendesk apps being used as an admin UI for Zendesk Integration Services", 6 | "installation_instructions": "Follow the instruction to install as a private app: https://developer.zendesk.com/documentation/apps/getting-started/uploading-and-installing-a-private-app/" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/.gitignore: -------------------------------------------------------------------------------- 1 | tmp 2 | .zat 3 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/README.md: -------------------------------------------------------------------------------- 1 | # ZIS Tutorial - Zendesk App as an admin interface 2 | 3 | This folder contains the source code for [Part 4: Connecting to Slack and installing the integration](https://developer.zendesk.com/documentation/integration-services/zis-tutorials/zendesk-app-admin-interface/create-config-ui/) 4 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/bootstrap.js: -------------------------------------------------------------------------------- 1 | // Bootstrap the app when DOM is ready 2 | $(function() { 3 | // Initialise the Zendesk JavaScript API client 4 | // https://developer.zendesk.com/apps/docs/developer-guide/getting_started 5 | window.client = ZAFClient.init(); 6 | 7 | // Subdomain is required to kick-off OAuth flow. See: connect.js 8 | let subdomain = undefined; 9 | 10 | // Integration key is the unique identifier for your integration app 11 | let integrationKey = undefined; 12 | 13 | client.context().then(function(context) { 14 | // Derive subdomain & integration key 15 | subdomain = context['account']['subdomain'] 16 | integrationKey = subdomain + "_zis_tutorial" 17 | console.log("Integration key: " + integrationKey); 18 | }).then(function() { 19 | // Bind button to start OAuth flow 20 | $("#btnConnect").click(function() { startOAuth(integrationKey, subdomain) }); 21 | 22 | // Bind button to start Slack OAuth flow 23 | $("#btnConnectSlack").click(function() { startSlackOAuth(integrationKey, subdomain) }); 24 | 25 | // Bind button to install the Flow 26 | $("#btnInstallFlow").click(function() { installFlow(integrationKey) }); 27 | 28 | // Bind button to submit config 29 | $("#submit").click(function() { submitConfig(integrationKey) }); 30 | 31 | // Fetch configuration data and render on UI 32 | fetchConfig(integrationKey); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/bundle.js: -------------------------------------------------------------------------------- 1 | // upsertBundle upserts the ZIS Bundle 2 | function upsertBundle(integrationKey) { 3 | const bundle = compileBundle(integrationKey) 4 | 5 | let request = { 6 | type: "POST", 7 | url: "/api/services/zis/registry/" + integrationKey + "/bundles", 8 | contentType: "application/json", 9 | data: JSON.stringify(bundle) 10 | }; 11 | 12 | return client.request(request).then( 13 | function(response) { 14 | console.log("Bundle upserted successfully") 15 | }, 16 | function(response) { 17 | console.log("Failed to upsert bundle: ", response) 18 | } 19 | ); 20 | } 21 | 22 | function compileBundle(integrationKey) { 23 | return { 24 | zis_template_version: '2019-10-14', 25 | name: 'RedactSensitiveDetailsOnComments', 26 | description: 'Redact sensitive details from comments such as email', 27 | resources: { 28 | redact_ticket_comment_flow: { 29 | type: 'ZIS::Flow', 30 | properties: { 31 | name: 'redact_ticket_comment', 32 | definition: { 33 | StartAt: 'VerifyTicketStatus', 34 | States: { 35 | VerifyTicketStatus: { 36 | Type: 'Action', 37 | ActionName: 'zis:common:transform:Jq', 38 | Parameters: { 39 | "expr.$": '.ticket_statuses | index(["{{$.input.ticket_event.ticket.status}}"])', 40 | data: '{"ticket_statuses": ["new","open","pending","solved","closed"]}' 41 | }, 42 | ResultPath: '$.ticket_status_index', 43 | Next: 'IsTicketStatusConfigured' 44 | }, 45 | IsTicketStatusConfigured: { 46 | Type: 'Choice', 47 | Choices: [ 48 | { 49 | Variable: '$.ticket_status_index', 50 | NumericGreaterThanEquals: 0, 51 | Next: 'RedactConfigs' 52 | } 53 | ], 54 | Default: 'Done' 55 | }, 56 | RedactConfigs: { 57 | Type: 'Action', 58 | ActionName: 'zis:common:transform:Jq', 59 | Parameters: { 60 | expr: '.items', 61 | data: '{"items": [{"name": "email", "regex": "[a-zA-Z0-9+_.-]+@[a-zA-Z0-9.-]+"}]}' 62 | }, 63 | ResultPath: '$.items', 64 | Next: 'RedactItems' 65 | }, 66 | RedactItems: { 67 | Type: 'Action', 68 | ActionName: 'zis:common:transform:Jq', 69 | Parameters: { 70 | "expr.$": '[.items[] | (.comment = "{{$.input.ticket_event.comment.body}}") | (.comment_id = "{{$.input.ticket_event.comment.id}}") |' + 71 | '(.ticket_id = "{{$.input.ticket_event.ticket.id}}") | (.connection = "{{$.connections.zendesk.access_token}}")]', 72 | "data.$": '$' 73 | }, 74 | ResultPath: '$.items', 75 | Next: 'RedactComment' 76 | }, 77 | RedactComment: { 78 | Type: 'Map', 79 | ItemsPath: '$.items', 80 | ResultPath: '$.redacted_description', 81 | Iterator: { 82 | StartAt: 'FindRedactMatch', 83 | States: { 84 | FindRedactMatch: { 85 | Type: 'Action', 86 | ActionName: 'zis:common:transform:Jq', 87 | Parameters: { 88 | "expr.$": '.comment | capture("(?{{$.regex}})"; "gi")', 89 | "data.$": '$' 90 | }, 91 | ResultPath: '$.capture', 92 | Next: 'RedactStringInComment' 93 | }, 94 | RedactStringInComment: { 95 | Type: 'Action', 96 | ActionName: "zis:" + integrationKey + ":action:redact_string_in_comment_http_action", 97 | Parameters: { 98 | "token.$": '$.connection', 99 | "ticket_id.$": '$.ticket_id', 100 | "comment_id.$": '$.comment_id', 101 | "redact_string.$": '$.capture.redact_string' 102 | }, 103 | ResultPath: '$.update_comment_results', 104 | Next: 'DoneMap' 105 | }, 106 | DoneMap: { 107 | Type: 'Succeed' 108 | } 109 | } 110 | }, 111 | End: true 112 | }, 113 | Done: { 114 | Type: 'Succeed' 115 | } 116 | } 117 | } 118 | } 119 | }, 120 | redact_comment_action: { 121 | type: 'ZIS::Action::Http', 122 | properties: { 123 | name: 'redact_string_in_comment_http_action', 124 | definition: { 125 | method: 'PUT', 126 | url: 'https://{{$.subdomain}}.{{$.zendeskHost}}/api/v2/tickets/{{$.ticket_id}}/comments/{{$.comment_id}}/redact.json', 127 | headers: [ 128 | { 129 | key: 'Authorization', 130 | value: 'Bearer {{$.token}}' 131 | }, 132 | { 133 | key: 'Content-Type', 134 | value: 'application/json' 135 | } 136 | ], 137 | requestBody: { 138 | text: '{{$.redact_string}}' 139 | } 140 | } 141 | } 142 | }, 143 | redact_ticket_comment_on_ticket: { 144 | type: 'ZIS::JobSpec', 145 | properties: { 146 | name: 'redact_ticket_comment_job_spec', 147 | event_source: 'support', 148 | event_type: 'ticket.CommentAdded', 149 | flow_name: "zis:" + integrationKey + ":flow:redact_ticket_comment" 150 | } 151 | } 152 | } 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/config.js: -------------------------------------------------------------------------------- 1 | // configScope is a custom defined key for referencing the configuration data 2 | let configScope = "slackNotification"; 3 | 4 | // scopeExists is a boolean flag to indicate if the config data exists 5 | // for a given scope 6 | let scopeExists = false; 7 | 8 | // fetchConfig defines the function to fetch config data 9 | function fetchConfig(integrationKey) { 10 | // Fetch config request 11 | let request = { 12 | type: "GET", 13 | url: "/api/services/zis/integrations/" + integrationKey + 14 | "/configs?filter[scope]=" + configScope 15 | }; 16 | 17 | client.request(request).then( 18 | function(response) { 19 | console.log("Config fetched successfully: ", response.configs[0].config) 20 | scopeExists = true; 21 | updateComponents(response.configs[0].config); 22 | }, 23 | function(response) { 24 | console.log("Config fetching failed: ", response) 25 | if (response.status == 404) { 26 | scopeExists = false; 27 | } 28 | } 29 | ); 30 | } 31 | 32 | // submitConfig maps the data from DOM and submit through ZIS Configs API 33 | function submitConfig(integrationKey) { 34 | // Prepare the config payload 35 | let data = JSON.stringify({ 36 | scope: configScope, 37 | config: { 38 | priority: $("#select-priority").val(), 39 | channel: $("#txt-channel").val() 40 | } 41 | }); 42 | 43 | // The request is for create or update config data 44 | let request; 45 | 46 | if (scopeExists) { 47 | // request for update config 48 | request = { 49 | type: "PUT", 50 | url: "/api/services/zis/integrations/" + integrationKey + "/configs/" + configScope, 51 | contentType: "application/json", 52 | data: data 53 | }; 54 | } else { 55 | // request for create config 56 | request = { 57 | type: "POST", 58 | url: "/api/services/zis/integrations/" + integrationKey + "/configs", 59 | contentType: "application/json", 60 | data: data 61 | }; 62 | } 63 | 64 | client.request(request).then( 65 | function(response) { 66 | console.log("Config submitted successfully: ", response); 67 | client.invoke('notify', "Submitted successfully"); 68 | scopeExists = true; 69 | }, 70 | function(response) { 71 | console.log("Config submission failed: ", response); 72 | } 73 | ); 74 | } 75 | 76 | // updateComponents updates the UI components with the newly fetched config data 77 | function updateComponents(config) { 78 | console.log("Updating components with config: ", config); 79 | $("#select-priority").val(config.priority); 80 | $("#txt-channel").val(config.channel); 81 | } 82 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/connect.js: -------------------------------------------------------------------------------- 1 | // zendeskConnectionName is a human-friendly name for referencing 2 | // Zendesk OAuth connection stored in ZIS 3 | const zendeskConnectionName = "zendesk"; 4 | 5 | // zendeskOAuthClientName is used to reference the companion Zendesk OAuth 6 | // client that came with the ZIS integration 7 | const zendeskOAuthClientName = "zendesk"; 8 | 9 | function startOAuth(integrationKey, subdomain) { 10 | let data = JSON.stringify({ 11 | name: zendeskConnectionName, 12 | oauth_client_name: zendeskOAuthClientName, 13 | oauth_url_subdomain: subdomain, 14 | origin_oauth_redirect_url: window.location.href, 15 | permission_scopes: "read write" 16 | }); 17 | 18 | let request = { 19 | type: "POST", 20 | url: "/api/services/zis/connections/oauth/start/" + integrationKey, 21 | contentType: "application/json", 22 | data: data 23 | }; 24 | 25 | client.request(request).then( 26 | function(response) { 27 | console.log("OAuth started successfully"); 28 | authorize(response.redirect_url) 29 | }, 30 | function(response) { 31 | console.log("Failed to start OAuth: ", response); 32 | } 33 | ); 34 | }; 35 | 36 | function authorize(redirectURL) { 37 | let authWindow = window.open(redirectURL, '_blank') 38 | setTimeout(watchToken, 1500); 39 | // poll token from the newly opened window 40 | function watchToken() { 41 | try { 42 | let params = new URL(authWindow.location.href).searchParams; 43 | // Cross-origin access will cause error on the above line 44 | // Once the oauth is completed, the authWindow's location 45 | // will be redirected back to the same origin, which in turn 46 | // allow us to get the verification token 47 | let verificationToken = params.get('verification_token'); 48 | console.log("Successfully established connection"); 49 | authWindow.close(); 50 | } catch(err) { 51 | console.log("DOM error is expected during cross domain authorization: " + err); 52 | setTimeout(watchToken, 500) 53 | } 54 | } 55 | }; 56 | 57 | // startSlackOAuth initiates a Slack OAuth flow 58 | function startSlackOAuth(integrationKey, subdomain) { 59 | let data = JSON.stringify({ 60 | name: "slack", // the name the obtained access token 61 | oauth_client_name: "slack", 62 | oauth_url_subdomain: subdomain, 63 | origin_oauth_redirect_url: window.location.href, 64 | permission_scopes: "chat:write" 65 | }); 66 | 67 | let request = { 68 | type: "POST", 69 | url: "/api/services/zis/connections/oauth/start/" + integrationKey, 70 | contentType: "application/json", 71 | data: data 72 | }; 73 | 74 | client.request(request).then( 75 | function(response) { 76 | console.log("OAuth started successfully"); 77 | authorize(response.redirect_url) 78 | }, 79 | function(response) { 80 | console.log("Failed to start OAuth: ", response); 81 | } 82 | ); 83 | }; 84 | 85 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 |
33 |
34 | 35 |
36 |
37 | 38 |
39 |
40 | 41 |
42 |
43 |
44 |
45 | 46 | 52 |
53 |
54 |
55 |
56 | 57 | 58 |
59 |
60 |
61 |
62 |
63 | 64 |
65 |
66 |
67 |
68 |
69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/logo-small.png -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zendesk/demo_apps/6161eaf4fb1f183c123aaa4bd94ac682196be0ea/v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/logo.png -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 8 | 10 | 11 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/assets/registry.js: -------------------------------------------------------------------------------- 1 | // installFlow enable the workflow on the current Zendesk account. 2 | // The underlying concept of JobSpec is used to associate a workflow with a 3 | // triggering event. 4 | function installFlow(integrationKey) { 5 | const jobSpec = "zis:" + integrationKey + ":job_spec:post_message_to_slack_on_ticket_created_job_spec" 6 | 7 | let request = { 8 | type: "POST", 9 | url: "/api/services/zis/integrations/" + integrationKey + "/job_specs/installation", 10 | contentType: "application/json", 11 | data: JSON.stringify([{ "name": jobSpec }]) 12 | }; 13 | 14 | return client.request(request).then( 15 | function(response) { 16 | console.log("Flow enabled successfully") 17 | }, 18 | function(response) { 19 | console.log("Failed to enable flow: ", response) 20 | } 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ZIS Tutorial - Slack Notifier", 3 | "author": { 4 | "name": "Zendesk Integrations", 5 | "email": "integrations@zendesk.com", 6 | "url": "https://www.zendesk.com" 7 | }, 8 | "version": "1.0", 9 | "frameworkVersion": "2.0", 10 | "defaultLocale": "en", 11 | "private": true, 12 | "location": { 13 | "support": { 14 | "nav_bar": "assets/index.html" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /v2/zis/zendesk_app_as_admin_ui/part_3/src/translations/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": { 3 | "name": "ZIS Tutorial - Slack Notifier Part 3", 4 | "short_description": "An example app to show case Zendesk apps being used as an admin UI for Zendesk Integration Services", 5 | "long_description": "An example app to show case Zendesk apps being used as an admin UI for Zendesk Integration Services", 6 | "installation_instructions": "Follow the instruction to install as a private app: https://developer.zendesk.com/documentation/apps/getting-started/uploading-and-installing-a-private-app/" 7 | } 8 | } 9 | --------------------------------------------------------------------------------