From 8ee1b20cb6d764606fe4e99623487d3804e64ede Mon Sep 17 00:00:00 2001 From: James Tsay Date: Tue, 17 Sep 2024 21:00:13 -0700 Subject: [PATCH] Placeholder, Icon, Toast Updates --- acrobat/blocks/prompt-card/prompt-card.css | 9 +-- acrobat/blocks/prompt-card/prompt-card.js | 68 ++++++++++++------- acrobat/img/icons/aichat.svg | 28 ++++++-- .../prompt-card/mocks/body-block-icon.html | 28 ++++++++ test/blocks/prompt-card/mocks/body-block.html | 4 -- .../mocks/body-group-placeholder.html | 52 ++++++++++++++ test/blocks/prompt-card/mocks/body-group.html | 14 +--- .../prompt-card/mocks/body-section.html | 56 +-------------- .../mocks/body-template-group.html | 12 ---- .../prompt-card/mocks/body-template.html | 12 ---- .../blocks/prompt-card/mocks/placeholder.json | 11 +++ .../prompt-card-group-placeholder.test.js | 25 +++++++ .../prompt-card/prompt-card-icon.test.js | 34 ++++++++++ test/blocks/prompt-card/prompt-card.test.js | 10 ++- 14 files changed, 231 insertions(+), 132 deletions(-) create mode 100644 test/blocks/prompt-card/mocks/body-block-icon.html create mode 100644 test/blocks/prompt-card/mocks/body-group-placeholder.html create mode 100644 test/blocks/prompt-card/mocks/placeholder.json create mode 100644 test/blocks/prompt-card/prompt-card-group-placeholder.test.js create mode 100644 test/blocks/prompt-card/prompt-card-icon.test.js diff --git a/acrobat/blocks/prompt-card/prompt-card.css b/acrobat/blocks/prompt-card/prompt-card.css index ebf646d1..9d3988c6 100644 --- a/acrobat/blocks/prompt-card/prompt-card.css +++ b/acrobat/blocks/prompt-card/prompt-card.css @@ -15,8 +15,7 @@ position: fixed; top: 110px; transform: translate(-50%, -50%); - z-index: 1; - z-index: 11 + z-index: 9999 } .prompt-toast--show { @@ -61,6 +60,7 @@ padding: 20px 20px 24px; transition-delay: 3s; transition-property: border; + max-width: 276px; } .prompt-blade:hover { @@ -73,7 +73,7 @@ } .prompt-icon { - margin-right: 5px; + margin-inline-end: 5px; position: relative; top: 5px } @@ -153,5 +153,6 @@ min-width: 18px; position: relative; top: 5px; - width: 18px + width: 18px; + margin-inline-start: 8px } diff --git a/acrobat/blocks/prompt-card/prompt-card.js b/acrobat/blocks/prompt-card/prompt-card.js index 117c4b47..c9414fd3 100644 --- a/acrobat/blocks/prompt-card/prompt-card.js +++ b/acrobat/blocks/prompt-card/prompt-card.js @@ -4,11 +4,47 @@ const miloLibs = setLibs('/libs'); const { createTag } = await import(`${miloLibs}/utils/utils.js`); const classToastShow = 'prompt-toast--show'; +const getPlaceHolder = (x) => (window.mph?.[x] || x); + +function copyPrompt(cfg) { + navigator.clipboard.writeText(cfg.prompt); + + let toast = document.querySelector('.prompt-toast'); + if (!toast) { + toast = createTag('div', { class: 'prompt-toast' }, cfg.toast); + const toastClose = createTag('i', { class: 'prompt-close' }); + toast.appendChild(toastClose); + document.body.appendChild(toast); + + toastClose.addEventListener('click', () => { + toast.classList.remove(classToastShow); + }); + } + toast.childNodes[0].textContent = cfg.toast; + toast.classList.add(classToastShow); + + setTimeout(() => toast.classList.remove(classToastShow), 5000); +} async function createBlock(element, cfg) { - const blade = createTag('div', { class: 'prompt-blade' }); + cfg.icon = cfg.icon || '/acrobat/img/icons/aichat.svg'; + cfg.button = cfg.button || getPlaceHolder('Copy'); + cfg.toast = cfg.toast || getPlaceHolder('Copied to clipboard'); + const blade = createTag('div', { + class: 'prompt-blade', + title: cfg.prompt, + 'data-toast': cfg.toast, + 'daa-im': true, + 'daa-lh': 'Featured prompts | Executive summary', + }); const prefix = createTag('div', { class: 'prompt-prefix' }); - const icon = createTag('img', { class: 'prompt-icon', src: `/acrobat/img/icons/${cfg.icon}`, width: 18, height: 18 }); + const icon = createTag('img', { + class: 'prompt-icon', + alt: 'AI Assistant Icon', + src: cfg.icon, + width: 18, + height: 18, + }); const title = createTag('div', { class: 'prompt-title' }, cfg.title); const copy = createTag('div', { class: 'prompt-copy' }, cfg.prompt); const prompt = createTag('input', { id: 'prompt', value: cfg.prompt }); @@ -19,33 +55,17 @@ async function createBlock(element, cfg) { prefix.appendChild(createTag('span', null, cfg.prefix)); blade.append(prefix, title, copy, prompt, wrapper); element.replaceChildren(blade); - const toast = createTag('div', { class: 'prompt-toast' }, cfg.toast); - const toastClose = createTag('i', { class: 'prompt-close' }); - toast.appendChild(toastClose); - element.appendChild(toast); - - const copyPrompt = () => { - prompt.select(); - prompt.setSelectionRange(0, 99999); - navigator.clipboard.writeText(prompt.value); - toast.classList.add(classToastShow); - setTimeout(() => toast.classList.remove(classToastShow), 5000); - }; - - [copyBtn, blade].forEach((el) => el.addEventListener('click', () => { - copyPrompt(); - })); + + blade.addEventListener('click', () => { + copyPrompt(cfg); + }); copyBtn.addEventListener('keypress', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); - copyPrompt(); + copyPrompt(cfg); } }); - - toastClose.addEventListener('click', (e) => { - e.currentTarget.parentNode.classList.remove(classToastShow); - }); } async function processGroup(element, startIndex, templateCfg) { @@ -59,7 +79,7 @@ async function processGroup(element, startIndex, templateCfg) { for (const cfg of blockArray) { const blockEl = createTag('div', { class: 'prompt-card' }); await createBlock(blockEl, { ...templateCfg, ...cfg }); - element.parentNode.insertBefore(blockEl, element.nextSibling); + element.parentNode.insertBefore(blockEl, element.previousSibling); } element.remove(); } diff --git a/acrobat/img/icons/aichat.svg b/acrobat/img/icons/aichat.svg index a6e8260d..7d027e09 100644 --- a/acrobat/img/icons/aichat.svg +++ b/acrobat/img/icons/aichat.svg @@ -1,7 +1,21 @@ - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + diff --git a/test/blocks/prompt-card/mocks/body-block-icon.html b/test/blocks/prompt-card/mocks/body-block-icon.html new file mode 100644 index 00000000..e8ad0016 --- /dev/null +++ b/test/blocks/prompt-card/mocks/body-block-icon.html @@ -0,0 +1,28 @@ +
+
+
+
Icon
+
https://main--dc--adobecom.hlx.live/dc-shared/assets/images/frictionless/verb-footer-images/word-to-pdf.svg
+
+
+
Prefix
+
Ask
+
+
+
Title
+
Sum it up
+
+
+
Prompt
+
Summarize this document in 3 sentences.
+
+
+
Button
+
Copy
+
+
+
Toast
+
Copied to clipboard
+
+
+
diff --git a/test/blocks/prompt-card/mocks/body-block.html b/test/blocks/prompt-card/mocks/body-block.html index 4f448e53..6d5ea8c0 100644 --- a/test/blocks/prompt-card/mocks/body-block.html +++ b/test/blocks/prompt-card/mocks/body-block.html @@ -1,9 +1,5 @@
-
-
Icon
-
aichat.svg
-
Prefix
Ask
diff --git a/test/blocks/prompt-card/mocks/body-group-placeholder.html b/test/blocks/prompt-card/mocks/body-group-placeholder.html new file mode 100644 index 00000000..75afff64 --- /dev/null +++ b/test/blocks/prompt-card/mocks/body-group-placeholder.html @@ -0,0 +1,52 @@ +
+
+
+
+
Prefix
+
{{Ask}}
+
+
+
+
+
+
+
Title
+
Prompt
+
+
+
Sum it up
+
Summarize this document in 3 sentences.
+
+
+
Organize your thoughts
+
Suggest a few essay topics based on this reading that can help me get started.
+
+
+
Refresh your memory.
+
Provide 10 sample test questions that my professor could ask me.
+
+
+
Point out tech advantages
+
What are the key benefits for users of this proposed technology solution?
+
+
+
Point out tech advantages
+
What are the key benefits for users of this proposed technology solution?
+
+
+
Shorten up the intro
+
Rewrite the introduction so it has only 200 words and a Flesch reading score above 50.
+
+
+ +
+
\ No newline at end of file diff --git a/test/blocks/prompt-card/mocks/body-group.html b/test/blocks/prompt-card/mocks/body-group.html index 23f884ef..af38e0ef 100644 --- a/test/blocks/prompt-card/mocks/body-group.html +++ b/test/blocks/prompt-card/mocks/body-group.html @@ -1,22 +1,10 @@
-
-
Icon
-
aichat.svg
-
Prefix
Ask
-
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard!
-
+
diff --git a/test/blocks/prompt-card/mocks/body-section.html b/test/blocks/prompt-card/mocks/body-section.html index 3832d44d..71c1c088 100644 --- a/test/blocks/prompt-card/mocks/body-section.html +++ b/test/blocks/prompt-card/mocks/body-section.html @@ -1,18 +1,6 @@
-
-
Icon
-
aichat.svg
-
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard
-
Prefix
Ask
@@ -27,17 +15,13 @@
-
-
Icon
-
aichat.svg
-
Button
-
Copy
+
My Copy
Toast
-
Copied to Clipboard
+
My Copied to Clipboard
Prefix
@@ -53,18 +37,6 @@
-
-
Icon
-
aichat.svg
-
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard
-
Prefix
Brainstorm
@@ -79,18 +51,6 @@
-
-
Icon
-
aichat.svg
-
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard
-
Prefix
Analyze
@@ -105,18 +65,6 @@
-
-
Icon
-
aichat.svg
-
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard
-
Prefix
Modify
diff --git a/test/blocks/prompt-card/mocks/body-template-group.html b/test/blocks/prompt-card/mocks/body-template-group.html index 79bb91ab..67d6c0e3 100644 --- a/test/blocks/prompt-card/mocks/body-template-group.html +++ b/test/blocks/prompt-card/mocks/body-template-group.html @@ -1,22 +1,10 @@
-
-
Icon
-
aichat.svg
-
Prefix
Ask
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard!
-
diff --git a/test/blocks/prompt-card/mocks/body-template.html b/test/blocks/prompt-card/mocks/body-template.html index e346b3ab..8fd42370 100644 --- a/test/blocks/prompt-card/mocks/body-template.html +++ b/test/blocks/prompt-card/mocks/body-template.html @@ -1,22 +1,10 @@
-
-
Icon
-
aichat.svg
-
Prefix
Ask
-
-
Button
-
Copy
-
-
-
Toast
-
Copied to Clipboard!
-
diff --git a/test/blocks/prompt-card/mocks/placeholder.json b/test/blocks/prompt-card/mocks/placeholder.json new file mode 100644 index 00000000..558fcdad --- /dev/null +++ b/test/blocks/prompt-card/mocks/placeholder.json @@ -0,0 +1,11 @@ +{ + "total": 2, + "offset": 0, + "limit": 2, + "data": [ + { "key": "Ask", "value": "聞く"}, + { "key": "Copy", "value": "コピー" }, + { "key": "Copied to clipboard", "value": "クリップボードにコピーされました" } + ], + ":type": "sheet" +} diff --git a/test/blocks/prompt-card/prompt-card-group-placeholder.test.js b/test/blocks/prompt-card/prompt-card-group-placeholder.test.js new file mode 100644 index 00000000..d8aea259 --- /dev/null +++ b/test/blocks/prompt-card/prompt-card-group-placeholder.test.js @@ -0,0 +1,25 @@ +/* eslint-disable compat/compat */ +import { readFile } from '@web/test-runner-commands'; +import { expect } from '@esm-bundle/chai'; +import sinon from 'sinon'; +import { waitForElement } from '../../helpers/waitfor.js'; + +describe('prompt-cards in a section using the group feature', () => { + before(async () => { + const placeholder = await readFile({ path: './mocks/placeholder.json' }); + sinon.stub(window, 'fetch'); + const res = new window.Response(placeholder, { status: 200 }); + window.fetch.returns(Promise.resolve(res)); + document.head.innerHTML = await readFile({ path: './mocks/head.html' }); + document.body.innerHTML = await readFile({ path: './mocks/body-group-placeholder.html' }); + await import('../../../acrobat/scripts/scripts.js'); + await waitForElement('.prompt-blade'); + }); + + it('shows replaced placeholder text', async () => { + const prefix = document.querySelector('.prompt-prefix'); + expect(prefix.textContent).to.equal('聞く'); + const button = document.querySelector('.prompt-copy-btn'); + expect(button.textContent).to.equal('コピー'); + }); +}); diff --git a/test/blocks/prompt-card/prompt-card-icon.test.js b/test/blocks/prompt-card/prompt-card-icon.test.js new file mode 100644 index 00000000..bb9d7686 --- /dev/null +++ b/test/blocks/prompt-card/prompt-card-icon.test.js @@ -0,0 +1,34 @@ +import { readFile } from '@web/test-runner-commands'; +import { expect } from '@esm-bundle/chai'; +import sinon from 'sinon'; + +const head = await readFile({ path: './mocks/head-block.html' }); + +const { default: init } = await import( + '../../../acrobat/blocks/prompt-card/prompt-card.js' +); + +describe('prompt-card block', () => { + let clock; + + before(async () => { + document.head.innerHTML = head; + document.body.innerHTML = await readFile({ path: './mocks/body-block-icon.html' }); + const block = document.querySelector('.prompt-card'); + await init(block); + }); + + beforeEach(() => { + clock = sinon.useFakeTimers(); + }); + + afterEach(() => { + clock.restore(); + }); + + it('has a customized icon', async () => { + const icon = document.querySelector('.prompt-icon'); + expect(icon).to.be.exist; + expect(icon.src).to.contains('word-to-pdf.svg'); + }); +}); diff --git a/test/blocks/prompt-card/prompt-card.test.js b/test/blocks/prompt-card/prompt-card.test.js index 0f10b97e..9bb94d13 100644 --- a/test/blocks/prompt-card/prompt-card.test.js +++ b/test/blocks/prompt-card/prompt-card.test.js @@ -36,7 +36,10 @@ describe('prompt-card block', () => { }); it('copies the prompt when copy button is clicked', async () => { - expect(document.querySelector('.prompt-toast').checkVisibility()).to.be.false; + const toast = document.querySelector('.prompt-toast'); + if (toast) { + expect(toast.checkVisibility()).to.be.false; + } document.querySelector('.prompt-copy-btn').click(); expect(document.querySelector('.prompt-toast').checkVisibility()).to.be.true; expect(document.querySelector('.prompt-close')).to.be.exist; @@ -47,7 +50,10 @@ describe('prompt-card block', () => { it('copies the prompt when key press ENTER/SPACE on copy button', () => { const keys = ['Enter', ' ']; keys.forEach((key) => { - expect(document.querySelector('.prompt-toast').checkVisibility()).to.be.false; + const toast = document.querySelector('.prompt-toast'); + if (toast) { + expect(toast.checkVisibility()).to.be.false; + } document.querySelector('.prompt-copy-btn').dispatchEvent(new KeyboardEvent('keypress', { key })); expect(document.querySelector('.prompt-toast').checkVisibility()).to.be.true; expect(document.querySelector('.prompt-close')).to.be.exist;