@nyaruka/temba-components 0.43.0 → 0.43.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/{96498fd6.js → 850b9c76.js} +434 -412
- package/dist/index.js +434 -412
- package/dist/sw.js +1 -1
- package/dist/sw.js.map +1 -1
- package/dist/templates/components-body.html +1 -1
- package/dist/templates/components-head.html +1 -1
- package/out-tsc/src/compose/Compose.js +47 -50
- package/out-tsc/src/compose/Compose.js.map +1 -1
- package/out-tsc/src/contacts/ContactChat.js +2 -2
- package/out-tsc/src/contacts/ContactChat.js.map +1 -1
- package/out-tsc/src/dialog/Dialog.js +0 -2
- package/out-tsc/src/dialog/Dialog.js.map +1 -1
- package/out-tsc/src/dropdown/Dropdown.js +0 -1
- package/out-tsc/src/dropdown/Dropdown.js.map +1 -1
- package/out-tsc/src/lightbox/Lightbox.js +10 -7
- package/out-tsc/src/lightbox/Lightbox.js.map +1 -1
- package/out-tsc/src/list/ContentMenu.js +0 -4
- package/out-tsc/src/list/ContentMenu.js.map +1 -1
- package/out-tsc/src/list/TembaMenu.js +47 -18
- package/out-tsc/src/list/TembaMenu.js.map +1 -1
- package/out-tsc/src/utils/index.js +10 -1
- package/out-tsc/src/utils/index.js.map +1 -1
- package/out-tsc/test/temba-compose.test.js +5 -7
- package/out-tsc/test/temba-compose.test.js.map +1 -1
- package/out-tsc/test/temba-contact-chat.test.js +12 -12
- package/out-tsc/test/temba-contact-chat.test.js.map +1 -1
- package/package.json +1 -1
- package/screenshots/truth/menu/menu-focused-with items.png +0 -0
- package/screenshots/truth/menu/menu-refresh-1.png +0 -0
- package/screenshots/truth/menu/menu-refresh-2.png +0 -0
- package/screenshots/truth/menu/menu-root.png +0 -0
- package/screenshots/truth/menu/menu-submenu.png +0 -0
- package/screenshots/truth/menu/menu-tasks-nextup.png +0 -0
- package/screenshots/truth/menu/menu-tasks.png +0 -0
- package/src/compose/Compose.ts +54 -55
- package/src/contacts/ContactChat.ts +2 -2
- package/src/dialog/Dialog.ts +0 -2
- package/src/dropdown/Dropdown.ts +0 -1
- package/src/lightbox/Lightbox.ts +13 -9
- package/src/list/ContentMenu.ts +0 -4
- package/src/list/TembaMenu.ts +47 -18
- package/src/utils/index.ts +8 -1
- package/test/temba-compose.test.ts +5 -8
- package/test/temba-contact-chat.test.ts +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"temba-contact-chat.test.js","sourceRoot":"","sources":["../../test/temba-contact-chat.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { useFakeTimers } from 'sinon';\nimport { Button } from '../src/button/Button';\nimport { Compose } from '../src/compose/Compose';\nimport { ContactChat } from '../src/contacts/ContactChat';\nimport { CustomEventType } from '../src/interfaces';\nimport { TicketList } from '../src/list/TicketList';\nimport {\n assertScreenshot,\n clearMockPosts,\n getClip,\n getComponent,\n loadStore,\n mockGET,\n mockNow,\n mockPOST,\n} from '../test/utils.test';\nimport {\n getFailText,\n getSuccessFiles,\n getSuccessText,\n updateComponent,\n} from './temba-compose.test';\n\nlet clock: any;\nmockNow('2021-03-31T00:31:00.000-00:00');\n\nconst TAG = 'temba-contact-chat';\nconst getContactChat = async (attrs: any = {}) => {\n attrs['endpoint'] = '/test-assets/contacts/';\n // add some sizes and styles to force our chat history to scroll\n const chat = (await getComponent(\n TAG,\n attrs,\n '',\n 500,\n 500,\n 'display:flex;flex-direction:column;flex-grow:1;min-height:0;'\n )) as ContactChat;\n\n // TODO: this should be waiting for an event instead\n await waitFor(100);\n return chat;\n};\n\nconst list_TAG = 'temba-list';\nconst getTicketList = async (attrs: any = {}) => {\n const list = (await getComponent(list_TAG, attrs)) as TicketList;\n\n if (!list.endpoint) {\n return list;\n }\n\n return new Promise<TicketList>(resolve => {\n list.addEventListener(\n CustomEventType.FetchComplete,\n async () => {\n resolve(list);\n },\n { once: true }\n );\n });\n};\n\ndescribe('temba-contact-chat - contact tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same historylist for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('can be created', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot('contacts/contact-active-default', getClip(chat));\n });\n\n it('show history and show chatbox if contact is active', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot(\n 'contacts/contact-active-show-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is archived', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n await assertScreenshot(\n 'contacts/contact-archived-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is blocked', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-michelle-blocked',\n });\n\n await assertScreenshot(\n 'contacts/contact-blocked-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is stopped', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-tim-stopped',\n });\n\n await assertScreenshot(\n 'contacts/contact-stopped-hide-chatbox',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - text no attachments', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with text no attachments - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText());\n\n const response_body = {\n contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],\n text: { eng: 'sà-wàd-dee!' },\n attachments: { eng: [] },\n };\n mockPOST(/api\\/v2\\/broadcasts\\.json/, response_body);\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-no-attachments-success',\n getClip(chat)\n );\n });\n\n it('with text no attachments - failure - more than 640 chars', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n await updateComponent(compose, getFailText());\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-no-attachments-failure',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - attachments no text', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with attachments no text - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n const attachments = getSuccessFiles();\n await updateComponent(compose, null, attachments);\n const response_body = {\n contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],\n text: { eng: '' },\n attachments: { eng: attachments },\n };\n const response_headers = {};\n const response_status = '200';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-attachments-no-text-success',\n getClip(chat)\n );\n });\n it('with attachments no text - failure - more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, null, getSuccessFiles(11));\n\n const response_body = {\n attachments: { eng: ['Ensure this field has no more than 10 elements.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-attachments-no-text-failure',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - text and attachments', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with text and attachments - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText(), getSuccessFiles());\n\n const text = getSuccessText();\n const attachments = getSuccessFiles();\n const response_body = {\n contacts: [{ uuid: 'contact-dave-active', name: 'Dave Matthews' }],\n text: { eng: text },\n attachments: { eng: attachments },\n };\n mockPOST(/api\\/v2\\/broadcasts\\.json/, response_body);\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-success',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 640 chars', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n await updateComponent(compose, getFailText(), getSuccessFiles());\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-text',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, getSuccessText(), getSuccessFiles(11));\n\n const response_body = {\n attachments: { eng: ['Ensure this field has no more than 10 elements.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-attachments',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 640 chars and more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, getFailText(), getSuccessFiles(11));\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-text-and-attachments',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - generic', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText(), getSuccessFiles());\n\n const response_body = {};\n const response_headers = {};\n const response_status = '500';\n mockPOST(\n /api\\/v2\\/broadcasts\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-generic',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - ticket tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same history for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n\n mockGET(/\\/api\\/v2\\/tickets\\.json.*/, '/test-assets/tickets/empty.json');\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('show history and show chatbox if contact is active and ticket is open', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-open.json',\n });\n\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n // we want to wait until our scroll is finished before taking our screenshot\n // once we have two scrollTops that are the same, we'll assume we're ready\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-active-ticket-open-show-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n\n it('show history and show reopen button if contact is active and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-active-ticket-closed-show-reopen-button',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n\n it('show history and hide chatbox if contact is archived and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-barack-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-archived-ticket-closed-hide-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"temba-contact-chat.test.js","sourceRoot":"","sources":["../../test/temba-contact-chat.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { useFakeTimers } from 'sinon';\nimport { Button } from '../src/button/Button';\nimport { Compose } from '../src/compose/Compose';\nimport { ContactChat } from '../src/contacts/ContactChat';\nimport { CustomEventType } from '../src/interfaces';\nimport { TicketList } from '../src/list/TicketList';\nimport {\n assertScreenshot,\n clearMockPosts,\n getClip,\n getComponent,\n loadStore,\n mockGET,\n mockNow,\n mockPOST,\n} from '../test/utils.test';\nimport {\n getFailText,\n getSuccessFiles,\n getSuccessText,\n updateComponent,\n} from './temba-compose.test';\n\nlet clock: any;\nmockNow('2021-03-31T00:31:00.000-00:00');\n\nconst TAG = 'temba-contact-chat';\nconst getContactChat = async (attrs: any = {}) => {\n attrs['endpoint'] = '/test-assets/contacts/';\n // add some sizes and styles to force our chat history to scroll\n const chat = (await getComponent(\n TAG,\n attrs,\n '',\n 500,\n 500,\n 'display:flex;flex-direction:column;flex-grow:1;min-height:0;'\n )) as ContactChat;\n\n // TODO: this should be waiting for an event instead\n await waitFor(100);\n return chat;\n};\n\nconst list_TAG = 'temba-list';\nconst getTicketList = async (attrs: any = {}) => {\n const list = (await getComponent(list_TAG, attrs)) as TicketList;\n\n if (!list.endpoint) {\n return list;\n }\n\n return new Promise<TicketList>(resolve => {\n list.addEventListener(\n CustomEventType.FetchComplete,\n async () => {\n resolve(list);\n },\n { once: true }\n );\n });\n};\n\ndescribe('temba-contact-chat - contact tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same historylist for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('can be created', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot('contacts/contact-active-default', getClip(chat));\n });\n\n it('show history and show chatbox if contact is active', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n\n await assertScreenshot(\n 'contacts/contact-active-show-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is archived', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n await assertScreenshot(\n 'contacts/contact-archived-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is blocked', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-michelle-blocked',\n });\n\n await assertScreenshot(\n 'contacts/contact-blocked-hide-chatbox',\n getClip(chat)\n );\n });\n\n it('show history and hide chatbox if contact is stopped', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-tim-stopped',\n });\n\n await assertScreenshot(\n 'contacts/contact-stopped-hide-chatbox',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - text no attachments', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with text no attachments - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText());\n\n const response_body = {\n contact: { uuid: 'contact-dave-active', name: 'Dave Matthews' },\n text: { eng: 'sà-wàd-dee!' },\n attachments: { eng: [] },\n };\n mockPOST(/api\\/v2\\/messages\\.json/, response_body);\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-no-attachments-success',\n getClip(chat)\n );\n });\n\n it('with text no attachments - failure - more than 640 chars', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n await updateComponent(compose, getFailText());\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-no-attachments-failure',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - attachments no text', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with attachments no text - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n const attachments = getSuccessFiles();\n await updateComponent(compose, null, attachments);\n const response_body = {\n contact: { uuid: 'contact-dave-active', name: 'Dave Matthews' },\n text: { eng: '' },\n attachments: { eng: attachments },\n };\n const response_headers = {};\n const response_status = '200';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-attachments-no-text-success',\n getClip(chat)\n );\n });\n it('with attachments no text - failure - more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, null, getSuccessFiles(11));\n\n const response_body = {\n attachments: { eng: ['Ensure this field has no more than 10 elements.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-attachments-no-text-failure',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - contact tests - handle send tests - text and attachments', () => {\n beforeEach(() => {\n clearMockPosts();\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('with text and attachments - success', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText(), getSuccessFiles());\n\n const text = getSuccessText();\n const attachments = getSuccessFiles();\n const response_body = {\n contact: { uuid: 'contact-dave-active', name: 'Dave Matthews' },\n text: { eng: text },\n attachments: { eng: attachments },\n };\n mockPOST(/api\\/v2\\/messages\\.json/, response_body);\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-success',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 640 chars', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n await updateComponent(compose, getFailText(), getSuccessFiles());\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-text',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, getSuccessText(), getSuccessFiles(11));\n\n const response_body = {\n attachments: { eng: ['Ensure this field has no more than 10 elements.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-attachments',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - more than 640 chars and more than 10 files', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n // set the chatbox to a string that is 640+ chars\n // set the attachments to a list that is 10+ items\n await updateComponent(compose, getFailText(), getSuccessFiles(11));\n\n const response_body = {\n text: { eng: ['Ensure this field has no more than 640 characters.'] },\n };\n const response_headers = {};\n const response_status = '400';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-text-and-attachments',\n getClip(chat)\n );\n });\n\n it('with text and attachments - failure - generic', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-dave-active',\n });\n const compose = chat.shadowRoot.querySelector('temba-compose') as Compose;\n await updateComponent(compose, getSuccessText(), getSuccessFiles());\n\n const response_body = {};\n const response_headers = {};\n const response_status = '500';\n mockPOST(\n /api\\/v2\\/messages\\.json/,\n response_body,\n response_headers,\n response_status\n );\n\n const send = compose.shadowRoot.querySelector(\n 'temba-button#send-button'\n ) as Button;\n send.click();\n\n await assertScreenshot(\n 'contacts/compose-text-and-attachments-failure-generic',\n getClip(chat)\n );\n });\n});\n\ndescribe('temba-contact-chat - ticket tests', () => {\n // map requests for contact history to our static files\n // we'll just us the same history for everybody for now\n beforeEach(() => {\n mockGET(\n /\\/contact\\/history\\/contact-.*/,\n '/test-assets/contacts/history.json'\n );\n\n mockGET(/\\/api\\/v2\\/tickets\\.json.*/, '/test-assets/tickets/empty.json');\n clock = useFakeTimers();\n });\n\n afterEach(function () {\n clock.restore();\n });\n\n it('show history and show chatbox if contact is active and ticket is open', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-open.json',\n });\n\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n // we want to wait until our scroll is finished before taking our screenshot\n // once we have two scrollTops that are the same, we'll assume we're ready\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-active-ticket-open-show-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n\n it('show history and show reopen button if contact is active and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n const chat: ContactChat = await getContactChat({\n contact: 'contact-carter-active',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-carter-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-active-ticket-closed-show-reopen-button',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n\n it('show history and hide chatbox if contact is archived and ticket is closed', async () => {\n // we are a StoreElement, so load a store first\n await loadStore();\n\n const chat: ContactChat = await getContactChat({\n contact: 'contact-barack-archived',\n });\n\n const tickets: TicketList = await getTicketList({\n endpoint: '/test-assets/tickets/ticket-barack-closed.json',\n });\n chat.currentTicket = tickets.items[0];\n chat.refresh();\n await chat.httpComplete;\n let lastScroll = 0;\n await assertScreenshot(\n 'contacts/contact-archived-ticket-closed-hide-chatbox',\n getClip(chat),\n {\n clock: clock,\n predicate: () => {\n const currentScroll = chat\n .getContactHistory()\n .getEventsPane().scrollTop;\n if (currentScroll !== 0 && currentScroll === lastScroll) {\n return true;\n }\n lastScroll = currentScroll;\n },\n }\n );\n });\n});\n"]}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/compose/Compose.ts
CHANGED
|
@@ -12,17 +12,20 @@ import {
|
|
|
12
12
|
WebResponse,
|
|
13
13
|
} from '../utils';
|
|
14
14
|
import { Completion } from '../completion/Completion';
|
|
15
|
+
import { VectorIcon } from '../vectoricon/VectorIcon';
|
|
16
|
+
import { Button } from '../button/Button';
|
|
15
17
|
|
|
16
18
|
export interface Attachment {
|
|
17
19
|
uuid: string;
|
|
18
20
|
content_type: string;
|
|
19
|
-
type: string; //deprecated
|
|
20
21
|
url: string;
|
|
21
|
-
|
|
22
|
+
filename: string;
|
|
22
23
|
size: number;
|
|
23
24
|
error: string;
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
export const upload_endpoint = '/api/v2/media.json';
|
|
28
|
+
|
|
26
29
|
export class Compose extends FormElement {
|
|
27
30
|
static get styles() {
|
|
28
31
|
return css`
|
|
@@ -199,7 +202,7 @@ export class Compose extends FormElement {
|
|
|
199
202
|
accept = ''; //e.g. ".xls,.xlsx"
|
|
200
203
|
|
|
201
204
|
@property({ type: String, attribute: false })
|
|
202
|
-
endpoint =
|
|
205
|
+
endpoint = upload_endpoint;
|
|
203
206
|
|
|
204
207
|
@property({ type: Boolean, attribute: false })
|
|
205
208
|
uploading: boolean;
|
|
@@ -225,23 +228,27 @@ export class Compose extends FormElement {
|
|
|
225
228
|
public updated(changes: Map<string, any>): void {
|
|
226
229
|
super.updated(changes);
|
|
227
230
|
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
changes.has('values') ||
|
|
231
|
-
changes.has('buttonError')
|
|
232
|
-
) {
|
|
231
|
+
if (changes.has('currentChat') || changes.has('values')) {
|
|
232
|
+
this.buttonError = '';
|
|
233
233
|
this.toggleButton();
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
firstUpdated(): void {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
238
|
+
this.setFocusOnChatbox();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
setFocusOnChatbox(): void {
|
|
242
|
+
if (this.chatbox) {
|
|
243
|
+
const completion = this.shadowRoot.querySelector(
|
|
244
|
+
'temba-completion'
|
|
245
|
+
) as Completion;
|
|
246
|
+
if (completion) {
|
|
247
|
+
//simulate a click inside the completion to set focus
|
|
248
|
+
window.setTimeout(() => {
|
|
249
|
+
completion.click();
|
|
250
|
+
}, 0);
|
|
251
|
+
}
|
|
245
252
|
}
|
|
246
253
|
}
|
|
247
254
|
|
|
@@ -334,19 +341,21 @@ export class Compose extends FormElement {
|
|
|
334
341
|
payload.append('file', file);
|
|
335
342
|
postFormData(url, payload)
|
|
336
343
|
.then((response: WebResponse) => {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
if (attachment) {
|
|
342
|
-
this.addValue(attachment);
|
|
343
|
-
this.fireCustomEvent(CustomEventType.AttachmentAdded, attachment);
|
|
344
|
-
}
|
|
344
|
+
const attachment = response.json as Attachment;
|
|
345
|
+
if (attachment) {
|
|
346
|
+
this.addValue(attachment);
|
|
347
|
+
this.fireCustomEvent(CustomEventType.AttachmentAdded, attachment);
|
|
345
348
|
}
|
|
346
349
|
})
|
|
347
|
-
.catch((error:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
+
.catch((error: WebResponse) => {
|
|
351
|
+
let fileError = '';
|
|
352
|
+
if (error.status === 400) {
|
|
353
|
+
fileError = error.json.file[0];
|
|
354
|
+
} else {
|
|
355
|
+
fileError = 'Server failure';
|
|
356
|
+
}
|
|
357
|
+
console.error(fileError);
|
|
358
|
+
this.addErrorValue(file, fileError);
|
|
350
359
|
})
|
|
351
360
|
.finally(() => {
|
|
352
361
|
this.uploading = false;
|
|
@@ -357,12 +366,11 @@ export class Compose extends FormElement {
|
|
|
357
366
|
const errorValue = {
|
|
358
367
|
uuid: Math.random().toString(36).slice(2, 6),
|
|
359
368
|
content_type: file.type,
|
|
360
|
-
|
|
361
|
-
name: file.name,
|
|
369
|
+
filename: file.name,
|
|
362
370
|
url: file.name,
|
|
363
371
|
size: file.size,
|
|
364
372
|
error: error,
|
|
365
|
-
};
|
|
373
|
+
} as Attachment;
|
|
366
374
|
this.errorValues.push(errorValue);
|
|
367
375
|
this.requestUpdate('errorValues');
|
|
368
376
|
}
|
|
@@ -392,20 +400,16 @@ export class Compose extends FormElement {
|
|
|
392
400
|
|
|
393
401
|
public toggleButton() {
|
|
394
402
|
if (this.button) {
|
|
395
|
-
|
|
396
|
-
|
|
403
|
+
const chatboxEmpty = this.currentChat.trim().length === 0;
|
|
404
|
+
const attachmentsEmpty = this.values.length === 0;
|
|
405
|
+
if (this.chatbox && this.attachments) {
|
|
406
|
+
this.buttonDisabled = chatboxEmpty && attachmentsEmpty;
|
|
407
|
+
} else if (this.chatbox) {
|
|
408
|
+
this.buttonDisabled = chatboxEmpty;
|
|
409
|
+
} else if (this.attachments) {
|
|
410
|
+
this.buttonDisabled = attachmentsEmpty;
|
|
397
411
|
} else {
|
|
398
|
-
|
|
399
|
-
const attachmentsEmpty = this.values.length === 0;
|
|
400
|
-
if (this.chatbox && this.attachments) {
|
|
401
|
-
this.buttonDisabled = chatboxEmpty && attachmentsEmpty;
|
|
402
|
-
} else if (this.chatbox) {
|
|
403
|
-
this.buttonDisabled = chatboxEmpty;
|
|
404
|
-
} else if (this.attachments) {
|
|
405
|
-
this.buttonDisabled = attachmentsEmpty;
|
|
406
|
-
} else {
|
|
407
|
-
this.buttonDisabled = true;
|
|
408
|
-
}
|
|
412
|
+
this.buttonDisabled = true;
|
|
409
413
|
}
|
|
410
414
|
}
|
|
411
415
|
}
|
|
@@ -429,12 +433,9 @@ export class Compose extends FormElement {
|
|
|
429
433
|
this.buttonDisabled = true;
|
|
430
434
|
const name = this.buttonName;
|
|
431
435
|
this.fireCustomEvent(CustomEventType.ButtonClicked, { name });
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
436
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
this.buttonError = '';
|
|
437
|
+
//after send, return focus to chatbox
|
|
438
|
+
this.setFocusOnChatbox();
|
|
438
439
|
}
|
|
439
440
|
}
|
|
440
441
|
|
|
@@ -469,7 +470,6 @@ export class Compose extends FormElement {
|
|
|
469
470
|
@change=${this.handleChatboxChange}
|
|
470
471
|
@keydown=${this.handleSendEnter}
|
|
471
472
|
placeholder="Write something here"
|
|
472
|
-
@blur=${this.handleSendBlur}
|
|
473
473
|
>
|
|
474
474
|
</temba-completion>`;
|
|
475
475
|
}
|
|
@@ -492,13 +492,13 @@ export class Compose extends FormElement {
|
|
|
492
492
|
</div>
|
|
493
493
|
<div class="attachment-name">
|
|
494
494
|
<span
|
|
495
|
-
title="${attachment.
|
|
495
|
+
title="${attachment.filename} (${formatFileSize(
|
|
496
496
|
attachment.size,
|
|
497
497
|
2
|
|
498
|
-
)}) ${attachment.
|
|
499
|
-
>${truncate(attachment.
|
|
498
|
+
)}) ${attachment.content_type}"
|
|
499
|
+
>${truncate(attachment.filename, 25)}
|
|
500
500
|
(${formatFileSize(attachment.size, 0)})
|
|
501
|
-
${formatFileType(attachment.
|
|
501
|
+
${formatFileType(attachment.content_type)}</span
|
|
502
502
|
>
|
|
503
503
|
</div>
|
|
504
504
|
</div>`;
|
|
@@ -516,11 +516,11 @@ export class Compose extends FormElement {
|
|
|
516
516
|
</div>
|
|
517
517
|
<div class="attachment-name">
|
|
518
518
|
<span
|
|
519
|
-
title="${errorAttachment.
|
|
519
|
+
title="${errorAttachment.filename} (${formatFileSize(
|
|
520
520
|
0,
|
|
521
521
|
0
|
|
522
522
|
)}) - Attachment failed - ${errorAttachment.error}"
|
|
523
|
-
>${truncate(errorAttachment.
|
|
523
|
+
>${truncate(errorAttachment.filename, 25)}
|
|
524
524
|
(${formatFileSize(0, 0)}) - Attachment failed</span
|
|
525
525
|
>
|
|
526
526
|
</div>
|
|
@@ -579,7 +579,6 @@ export class Compose extends FormElement {
|
|
|
579
579
|
name=${this.buttonName}
|
|
580
580
|
@click=${this.handleSendClick}
|
|
581
581
|
?disabled=${this.buttonDisabled}
|
|
582
|
-
@blur=${this.handleSendBlur}
|
|
583
582
|
></temba-button>`;
|
|
584
583
|
}
|
|
585
584
|
}
|
|
@@ -267,7 +267,7 @@ export class ContactChat extends ContactStoreElement {
|
|
|
267
267
|
const buttonName = evt.detail.name;
|
|
268
268
|
if (buttonName === 'Send') {
|
|
269
269
|
const payload = {
|
|
270
|
-
|
|
270
|
+
contact: this.currentContact.uuid,
|
|
271
271
|
};
|
|
272
272
|
const compose = evt.currentTarget as Compose;
|
|
273
273
|
if (compose) {
|
|
@@ -289,7 +289,7 @@ export class ContactChat extends ContactStoreElement {
|
|
|
289
289
|
|
|
290
290
|
const genericError = buttonName + ' failed, please try again.';
|
|
291
291
|
|
|
292
|
-
postJSON(`/api/v2/
|
|
292
|
+
postJSON(`/api/v2/messages.json`, payload)
|
|
293
293
|
.then(response => {
|
|
294
294
|
if (response.status < 400) {
|
|
295
295
|
compose.reset();
|
package/src/dialog/Dialog.ts
CHANGED
|
@@ -215,14 +215,12 @@ export class Dialog extends RapidElement {
|
|
|
215
215
|
this.animationEnd = false;
|
|
216
216
|
}, 400);
|
|
217
217
|
|
|
218
|
-
const scrollbarWidth = window.outerWidth - body.clientWidth;
|
|
219
218
|
this.scrollOffset = -document.documentElement.scrollTop;
|
|
220
219
|
body.style.position = 'fixed';
|
|
221
220
|
body.style.overflowY = 'scroll';
|
|
222
221
|
body.style.top = this.scrollOffset + 'px';
|
|
223
222
|
body.style.width = '100%';
|
|
224
223
|
body.style.overflowY = 'hidden';
|
|
225
|
-
body.style.paddingRight = scrollbarWidth + 'px';
|
|
226
224
|
} else {
|
|
227
225
|
body.style.position = '';
|
|
228
226
|
body.style.overflowY = '';
|
package/src/dropdown/Dropdown.ts
CHANGED
package/src/lightbox/Lightbox.ts
CHANGED
|
@@ -93,18 +93,20 @@ export class Lightbox extends RapidElement {
|
|
|
93
93
|
|
|
94
94
|
let desiredWidth = this.width;
|
|
95
95
|
let desiredHeight = this.height;
|
|
96
|
+
let desiredScale = this.scale;
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
const maxHeight = window.innerHeight * this.zoomPct;
|
|
99
|
+
const maxWidth = window.innerWidth * this.zoomPct;
|
|
100
|
+
|
|
101
|
+
// if the width fits, constrain by height
|
|
102
|
+
if (this.width * (maxHeight / this.height) < maxWidth) {
|
|
99
103
|
desiredHeight = window.innerHeight * this.zoomPct;
|
|
100
|
-
|
|
101
|
-
desiredWidth = this.width *
|
|
102
|
-
}
|
|
103
|
-
// landscape
|
|
104
|
-
else {
|
|
104
|
+
desiredScale = desiredHeight / this.height;
|
|
105
|
+
desiredWidth = this.width * desiredScale;
|
|
106
|
+
} else {
|
|
105
107
|
desiredWidth = window.innerWidth * this.zoomPct;
|
|
106
|
-
|
|
107
|
-
desiredHeight = this.height *
|
|
108
|
+
desiredScale = desiredWidth / this.width;
|
|
109
|
+
desiredHeight = this.height * desiredScale;
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
const xGrowth = (desiredWidth - this.width) / 2;
|
|
@@ -114,6 +116,8 @@ export class Lightbox extends RapidElement {
|
|
|
114
116
|
const yGrowth = (desiredHeight - this.height) / 2;
|
|
115
117
|
const yDest = (window.innerHeight - desiredHeight) / 2;
|
|
116
118
|
this.yTrans = yDest - this.top + yGrowth + 'px';
|
|
119
|
+
|
|
120
|
+
this.scale = desiredScale;
|
|
117
121
|
this.show = true;
|
|
118
122
|
}
|
|
119
123
|
|
package/src/list/ContentMenu.ts
CHANGED
package/src/list/TembaMenu.ts
CHANGED
|
@@ -124,17 +124,39 @@ export class TembaMenu extends RapidElement {
|
|
|
124
124
|
|
|
125
125
|
.level-0 > .item,
|
|
126
126
|
.level-0 > temba-dropdown > div[slot='toggle'] > .avatar {
|
|
127
|
-
|
|
127
|
+
padding: 0px;
|
|
128
128
|
--icon-color: rgba(255, 255, 255, 0.7);
|
|
129
129
|
font-size: 1em;
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
border: 0px solid green;
|
|
132
|
+
width: 100%;
|
|
133
|
+
display: flex;
|
|
134
|
+
align-items: center;
|
|
130
135
|
}
|
|
131
136
|
|
|
132
|
-
.level-0 > .
|
|
133
|
-
|
|
137
|
+
.level-0 > .item.selected::before,
|
|
138
|
+
.level-0 > .item.selected::after {
|
|
139
|
+
content: ' ';
|
|
140
|
+
height: var(--curvature);
|
|
134
141
|
background: var(--color-primary-dark);
|
|
135
|
-
display:
|
|
136
|
-
|
|
137
|
-
|
|
142
|
+
display: block;
|
|
143
|
+
width: 100%;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.level-0 > .item.selected::before {
|
|
147
|
+
border-bottom-right-radius: var(--curvature);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.level-0 > .item > temba-tip {
|
|
151
|
+
padding: 1em;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.level-0 > .item.selected::after {
|
|
155
|
+
border-top-right-radius: var(--curvature);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.level-0 {
|
|
159
|
+
padding-top: var(--menu-padding) !important;
|
|
138
160
|
}
|
|
139
161
|
|
|
140
162
|
.level-0 > .empty {
|
|
@@ -148,6 +170,14 @@ export class TembaMenu extends RapidElement {
|
|
|
148
170
|
background: var(--color-primary-dark);
|
|
149
171
|
}
|
|
150
172
|
|
|
173
|
+
.level-0 > temba-dropdown.open > div[slot='toggle'] > .avatar {
|
|
174
|
+
background: transparent !important;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.level-0 {
|
|
178
|
+
background: var(--color-primary-dark);
|
|
179
|
+
}
|
|
180
|
+
|
|
151
181
|
temba-dropdown {
|
|
152
182
|
z-index: 1;
|
|
153
183
|
}
|
|
@@ -174,7 +204,7 @@ export class TembaMenu extends RapidElement {
|
|
|
174
204
|
}
|
|
175
205
|
|
|
176
206
|
.level-0 > .item.selected {
|
|
177
|
-
background:
|
|
207
|
+
background: white;
|
|
178
208
|
--icon-color: var(--color-primary-dark);
|
|
179
209
|
}
|
|
180
210
|
|
|
@@ -184,7 +214,12 @@ export class TembaMenu extends RapidElement {
|
|
|
184
214
|
|
|
185
215
|
.level-0 {
|
|
186
216
|
padding: 0px;
|
|
187
|
-
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.top {
|
|
220
|
+
display: flex;
|
|
221
|
+
align-items: center;
|
|
222
|
+
flex-direction: column;
|
|
188
223
|
}
|
|
189
224
|
|
|
190
225
|
.item {
|
|
@@ -208,7 +243,6 @@ export class TembaMenu extends RapidElement {
|
|
|
208
243
|
}
|
|
209
244
|
|
|
210
245
|
.level-0 > .item {
|
|
211
|
-
padding: 1em 1em;
|
|
212
246
|
margin-top: 0em;
|
|
213
247
|
border-radius: 0px;
|
|
214
248
|
min-width: inherit;
|
|
@@ -249,12 +283,12 @@ export class TembaMenu extends RapidElement {
|
|
|
249
283
|
}
|
|
250
284
|
|
|
251
285
|
.level-0 > .item:hover {
|
|
252
|
-
background: rgba(
|
|
286
|
+
background: rgba(255, 255, 255, 0.15);
|
|
253
287
|
--icon-color: #fff;
|
|
254
288
|
}
|
|
255
289
|
|
|
256
290
|
.level-0 > .item.selected:hover {
|
|
257
|
-
background:
|
|
291
|
+
background: white;
|
|
258
292
|
--icon-color: var(--color-primary-dark);
|
|
259
293
|
cursor: default;
|
|
260
294
|
}
|
|
@@ -272,13 +306,11 @@ export class TembaMenu extends RapidElement {
|
|
|
272
306
|
.level-1 {
|
|
273
307
|
transition: opacity 100ms linear, margin 200ms linear;
|
|
274
308
|
overflow-y: scroll;
|
|
275
|
-
z-index: 150;
|
|
276
309
|
}
|
|
277
310
|
|
|
278
311
|
.level-2 {
|
|
279
312
|
background: #fbfbfb;
|
|
280
313
|
overflow-y: auto;
|
|
281
|
-
z-index: 1000;
|
|
282
314
|
}
|
|
283
315
|
|
|
284
316
|
.level-2 .item .details {
|
|
@@ -889,9 +921,7 @@ export class TembaMenu extends RapidElement {
|
|
|
889
921
|
icon = renderAvatar({ name: menuItem.avatar });
|
|
890
922
|
}
|
|
891
923
|
|
|
892
|
-
const item = html`
|
|
893
|
-
class="item-top ${isSelected ? 'selected' : null} "
|
|
894
|
-
></div>
|
|
924
|
+
const item = html`
|
|
895
925
|
<div
|
|
896
926
|
id="menu-${menuItem.id}"
|
|
897
927
|
class="${itemClasses}"
|
|
@@ -946,8 +976,7 @@ export class TembaMenu extends RapidElement {
|
|
|
946
976
|
</div>
|
|
947
977
|
<div class="right"></div>
|
|
948
978
|
</div>
|
|
949
|
-
|
|
950
|
-
<div class="item-bottom ${isSelected ? 'selected' : null}"></div>`;
|
|
979
|
+
`;
|
|
951
980
|
|
|
952
981
|
if (menuItem.popup) {
|
|
953
982
|
return html`
|
package/src/utils/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-this-alias */
|
|
2
2
|
import { html, TemplateResult } from 'lit-html';
|
|
3
3
|
import { Button } from '../button/Button';
|
|
4
|
+
import { upload_endpoint } from '../compose/Compose';
|
|
4
5
|
import { Dialog } from '../dialog/Dialog';
|
|
5
6
|
import { ContactField, Ticket, User } from '../interfaces';
|
|
6
7
|
import ColorHash from 'color-hash';
|
|
@@ -241,10 +242,16 @@ export const postFormData = (
|
|
|
241
242
|
.then(response => {
|
|
242
243
|
if (response.status >= 200 && response.status < 300) {
|
|
243
244
|
resolve(response);
|
|
245
|
+
} else {
|
|
246
|
+
if (url === upload_endpoint) {
|
|
247
|
+
reject(response);
|
|
248
|
+
} else {
|
|
249
|
+
reject('Server failure');
|
|
250
|
+
}
|
|
244
251
|
}
|
|
245
|
-
reject('Server failure');
|
|
246
252
|
})
|
|
247
253
|
.catch(err => {
|
|
254
|
+
console.error(err);
|
|
248
255
|
reject(err);
|
|
249
256
|
});
|
|
250
257
|
});
|