Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev phone test harness #197

Open
wants to merge 44 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
cac2757
first attempt at fixing newline issue from message bodies
gyasi-eco Apr 24, 2023
8754e1b
remove format method call
gyasi-eco Apr 26, 2023
592988b
add changeset and update changeset version
gyasi-eco Apr 26, 2023
78b17ef
adding text area auto size component
gyasi-eco Apr 26, 2023
572d132
add to changeset
gyasi-eco Apr 26, 2023
1912981
remove textarea container
gyasi-eco Apr 26, 2023
ff99ef4
replace custom textarea styling with pasteb textarea component
gyasi-eco May 3, 2023
000b192
remove external resizeable textarea component
gyasi-eco May 3, 2023
3895a09
initial commit of replacing custom messagelog with chatlog
gyasi-eco May 16, 2023
1490940
upgrade paste version to 19.0.0
gyasi-eco May 17, 2023
47c985d
add ChatLog component
gyasi-eco May 23, 2023
78ae115
add editor state and onChange for ChatComposer
gyasi-eco May 23, 2023
ab90920
remove unused imports
gyasi-eco May 23, 2023
673e858
replace onChange event listener with CTA button click for form submis…
gyasi-eco Jun 8, 2023
f038db4
revert to onChange event and remove aria-label placeholder data
gyasi-eco Jun 13, 2023
1697505
upgrade react to 18, icons to 11.1 and locally define async in PhoneN…
gyasi-eco Jun 13, 2023
4010387
revert from paste chatlog to custom messaging component
gyasi-eco Jun 14, 2023
0ef9026
upgrade paste library and add ClearEditorPlugin
gyasi-eco Sep 1, 2023
c05e275
first attempt at fixing newline issue from message bodies
gyasi-eco Apr 24, 2023
0c6bf1f
remove format method call
gyasi-eco Apr 26, 2023
42406a4
adding text area auto size component
gyasi-eco Apr 26, 2023
05ecf19
add to changeset
gyasi-eco Apr 26, 2023
623b60e
remove textarea container
gyasi-eco Apr 26, 2023
5eb5800
replace custom textarea styling with pasteb textarea component
gyasi-eco May 3, 2023
3baf128
remove external resizeable textarea component
gyasi-eco May 3, 2023
671c7ac
add ChatLog component
gyasi-eco May 23, 2023
1a289a3
add editor state and onChange for ChatComposer
gyasi-eco May 23, 2023
9fa63c7
remove unused imports
gyasi-eco May 23, 2023
462fe09
replace onChange event listener with CTA button click for form submis…
gyasi-eco Jun 8, 2023
d1d49ff
revert to onChange event and remove aria-label placeholder data
gyasi-eco Jun 13, 2023
1d4f762
upgrade react to 18, icons to 11.1 and locally define async in PhoneN…
gyasi-eco Jun 13, 2023
2544749
revert from paste chatlog to custom messaging component
gyasi-eco Jun 14, 2023
0b2bf8c
upgrade paste library and add ClearEditorPlugin
gyasi-eco Sep 1, 2023
ad8be78
move dependencies to dev ui package.json
gyasi-eco Sep 7, 2023
0452402
implement clear editor plugin component using editor state
gyasi-eco Oct 5, 2023
95c73b5
resolve merge conflicts
gyasi-eco Oct 10, 2023
5954dd1
Merge branch 'main' into 167-paste-chat-replace-messagelog-component
gyasi-eco Nov 7, 2023
708fec6
add dummy test to ensure Jest is configured properly
gyasi-eco Mar 13, 2024
fc6be96
add jest to plugin with passing tests
gyasi-eco Mar 18, 2024
a27b942
add unit testing structure for async methods
gyasi-eco Apr 23, 2024
ec394fd
add babel smart preset
gyasi-eco May 1, 2024
d5a7856
remove unused folder
gyasi-eco May 1, 2024
e4b5acd
add phone number utils tests
gyasi-eco May 21, 2024
3098c2c
add is valid port test
gyasi-eco Jun 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/tender-geckos-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-labs/dev-phone-ui": patch
---

Preserve newlines in inbound and outbound sms.
Add react text area auto resize component.
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@
"packages/dev-phone-ui"
],
"devDependencies": {
"@changesets/cli": "^2.23.0",
"@babel/preset-typescript": "^7.24.1",
"@changesets/cli": "^2.26.1",
"turbo": "^1.2.16"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"redux": "^4.2.1"
}
}
5 changes: 5 additions & 0 deletions packages/dev-phone-ui/__tests__/SendSmsForm.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
describe('Addition', () => {
it('knows that 2 and 2 make 4', () => {
expect(2 + 2).toBe(4);
});
});
24 changes: 17 additions & 7 deletions packages/dev-phone-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"main": "dist/index.html",
"scripts": {
"build": "rm -rf dist && webpack --config webpack.prod.config.js --mode production",
"start": "webpack serve"
"start": "webpack serve",
"test": "jest"
},
"author": "twilio-labs",
"license": "MIT",
Expand All @@ -15,34 +16,43 @@
"devDependencies": {
"@babel/core": "^7.17.5",
"@babel/plugin-transform-react-jsx": "^7.17.3",
"@babel/preset-env": "^7.16.11",
"@babel/preset-react": "^7.16.7",
"@babel/preset-env": "^7.24.0",
"@babel/preset-react": "^7.23.3",
"@changesets/cli": "^2.26.1",
"babel-jest": "^29.7.0",
"babel-loader": "^9.0.0",
"css-loader": "^6.6.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^29.7.0",
"react-test-renderer": "^18.2.0",
"source-map-loader": "^3.0.1",
"style-loader": "^3.3.1",
"turbo": "^1.2.16",
"webpack": "^5.69.1",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4",
"webpack-license-plugin": "^4.2.2"
},
"dependencies": {
"@twilio-paste/core": "^19.0.0",
"@twilio-paste/icons": "^11.1.0",
"@twilio-paste/core": "^20.2.0",
"@twilio-paste/icons": "^12.1.0",
"@twilio/conversations": "^2.0.0",
"@twilio/voice-sdk": "^2.1.0",
"date-fns": "^2.28.0",
"konami": "^1.6.3",
"process": "^0.11.10",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.6",
"redux": "^4.1.2",
"redux-thunk": "^2.4.1",
"twilio-sync": "^3.0.6",
"util": "^0.12.4"
},
"overrides": {
"@twilio-paste/core": "^20.2.0",
"@twilio-paste/icons": "^12.1.0"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
Expand Down
14 changes: 7 additions & 7 deletions packages/dev-phone-ui/src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';
// import { render, screen } from '@testing-library/react';
// import App from './App';

test('Shows the owlwave', () => {
render(<App />);
const helloElement = screen.getByText(/:owlwave:/i);
expect(helloElement).toBeInTheDocument();
});
// test('Shows the owlwave', () => {
// render(<App />);
// const helloElement = screen.getByText(/:owlwave:/i);
// expect(helloElement).toBeInTheDocument();
// });
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,6 @@ const sortUnconfiguredNumbersFirstThenAlphabetically = (pn1, pn2) => {
return pn1.phoneNumber.localeCompare(pn2.phoneNumber);
};

const numPicker = async (currentNum, selectNum, getAvailableNums) => {
if (!currentNum) {
try {
const response = await fetch('/phone-numbers')
const data = await response.json()
data["phone-numbers"].sort(
sortUnconfiguredNumbersFirstThenAlphabetically
)
getAvailableNums(data["phone-numbers"]);
if (data["phone-numbers"].length !== 0) {
selectNum(
getPnDetailsByNumber(
data["phone-numbers"][0].phoneNumber,
data["phone-numbers"]
)
);
}
} catch (error) {
console.error(error)
}
}
}


function PhoneNumberPickerContainer({ children }) {
return <Box
maxWidth={"75%"}
Expand All @@ -70,13 +46,34 @@ function PhoneNumberPickerContainer({ children }) {
</Box>
}


function PhoneNumberPicker({ configureNumberInUse, phoneNumbers }) {
const [twilioPns, setTwilioPns] = useState(null);
const [selectedPn, setSelectedPn] = useState(null);

useEffect(() => {
numPicker(selectedPn, setSelectedPn, setTwilioPns);
useEffect( () => {
const asyncFn = async() => {
if (!selectedPn) {
try {
const response = await fetch('/phone-numbers')
const data = await response.json()
data["phone-numbers"].sort(
sortUnconfiguredNumbersFirstThenAlphabetically
)
setTwilioPns(data["phone-numbers"]);
if (data["phone-numbers"].length !== 0) {
setSelectedPn(
getPnDetailsByNumber(
data["phone-numbers"][0].phoneNumber,
data["phone-numbers"]
)
);
}
} catch (error) {
console.error(error)
}
}
}
asyncFn()
}, [selectedPn]);

if (twilioPns === null) {
Expand Down
13 changes: 5 additions & 8 deletions packages/dev-phone-ui/src/components/SendSmsForm/MessageList.jsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import {
Box, Flex, SkeletonLoader,
Text, ChatLog, ChatMessage,
ChatBubble, ChatMessageMeta, ChatMessageMetaItem,
Avatar
} from "@twilio-paste/core"
import { UserIcon } from '@twilio-paste/icons/esm/UserIcon';
import { Box, SkeletonLoader } from "@twilio-paste/core"
import { ChatLog, ChatMessage, ChatBubble, ChatMessageMeta, ChatMessageMetaItem } from "@twilio-paste/chat-log";
import { Avatar } from "@twilio-paste/avatar";
import { useSelector } from "react-redux"
import EmptyMessageList from "./EmptyMessageList";



function MessageList({ devPhoneName }) {
const messageList = useSelector(state => state.messageList)
const numberInUse = useSelector(state => state.numberInUse ? state.numberInUse.phoneNumber : "");
Expand All @@ -27,7 +24,7 @@ function MessageList({ devPhoneName }) {
</ChatBubble>
<ChatMessageMeta aria-label={!isFromDevPhone ? "said by outbound user" : "said by dev phone"}>
<ChatMessageMetaItem>
<Avatar size="sizeIcon30" name={message.author} icon={UserIcon} />
<Avatar size="sizeIcon30" name={message.author} />
{message.author}
</ChatMessageMetaItem>
</ChatMessageMeta>
Expand Down
78 changes: 58 additions & 20 deletions packages/dev-phone-ui/src/components/SendSmsForm/SendSmsForm.jsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,46 @@
import { useContext, useState, useMemo } from "react";
import { Button, Input, Label, Box, Grid, Column } from "@twilio-paste/core";
import { SendIcon } from '@twilio-paste/icons/esm/SendIcon';
import React, { useContext, useState, useMemo } from "react";
import { useSelector } from "react-redux";
import { Button, Label, Box, Grid, HelpText, Column, AutoScrollPlugin } from "@twilio-paste/core";
import { ChatComposer } from "@twilio-paste/core/chat-composer";
import { SendIcon } from '@twilio-paste/icons/esm/SendIcon';
import { TwilioConversationsContext } from '../WebsocketManagers/ConversationsManager';
import MessageList from "./MessageList"
import {$getRoot, ClearEditorPlugin, useLexicalComposerContext, CLEAR_EDITOR_COMMAND } from "@twilio-paste/core/lexical-library";



function SendButtonPlugin({onClick, canSendMessages}) {
const [editor] = useLexicalComposerContext();

const sendIt = (e) => {
onClick(e);
editor.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
}


return (
<Button onClick={sendIt} type={"submit"} disabled={!canSendMessages}>
<SendIcon decorative />
Send
</Button>
)
}

function SendSmsForm({ numberInUse }) {
const myRef = React.createRef()

const [messageBody, setMessageBody] = useState('');

const channelData = useSelector(state => state.channelData)
const destinationNumber = useSelector(state => state.destinationNumber)

const conversationsClient = useContext(TwilioConversationsContext)
const {sendMessage, sendSms} = conversationsClient
const { sendMessage, sendSms } = conversationsClient

const canSendMessages = useMemo(() => {
return destinationNumber && destinationNumber.length > 6;
}, [destinationNumber]);

// Handles the UI state for sending messages
const sendIt = async (e) => {
e.preventDefault()
if (canSendMessages) {
Expand All @@ -30,25 +52,41 @@ function SendSmsForm({ numberInUse }) {
}
};

const myOnChange = (editorState) => {
editorState.read(() => {
const root = $getRoot();
setMessageBody(root.getTextContent());
});
};


return (
<Box width="100%" backgroundColor={"colorBackgroundBody"}>

<Box width="100%" backgroundColor={"default"}>
<MessageList
devPhoneName={channelData.devPhoneName}
/>
<form onSubmit={(e) => sendIt(e)} method={"GET"}>
<Label htmlFor="sendSmsBody" required>Message</Label>
<Grid gutter={"space20"} marginBottom="space40">
<Column span={10}>
<Input id="sendSmsBody" type="text" value={messageBody} onChange={(e) => setMessageBody(e.target.value)} />
</Column>
<Column span={2}>
<Button type={"submit"} disabled={!canSendMessages}>
<SendIcon decorative />
Send
</Button>
</Column>
</Grid>
</form>
<Label htmlFor="sendSmsBody" required>Message</Label>

<Grid gutter={"space20"} marginBottom="space40">
<Column span={10}>
<ChatComposer
config={{
namespace: "send_sms",
onError: (e) => {
throw e;
}
}}
placeholder="Chat text"
ariaLabel="A basic chat composer"
onChange={myOnChange}
>
<ClearEditorPlugin />
<SendButtonPlugin canSendMessages={canSendMessages} onClick={sendIt} />
</ChatComposer>
<HelpText id="send_sms_help_text">Enter at most 1600 characters</HelpText>
</Column>
</Grid>
</Box>

);
Expand Down
12 changes: 12 additions & 0 deletions packages/plugin-dev-phone/babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
"plugins": [
["@babel/plugin-transform-react-jsx", {
"runtime": "automatic"
}]
]
}
21 changes: 21 additions & 0 deletions packages/plugin-dev-phone/coverage-ts/assets/source-file.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.uncovered {
background: rgba(235, 26, 26, 0.3);
}
.CodeMirror {
border: 1px solid #ccc;
border-radius: 3px;
height: auto;
}
.TS-lineuncovered {
background: rgba(255, 255, 255, 0.3);
width: 24px;
}
/* NOTE: I have to increase the specificity because of semantic-ui */
p.footer-text {
text-align: center;
margin: 3em 0;
}
.gutter-marker {
text-align: center;
font-size: 0.6em;
}
40 changes: 40 additions & 0 deletions packages/plugin-dev-phone/coverage-ts/assets/source-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"use strict";

document.addEventListener("DOMContentLoaded", () => {
const myTextArea = document.getElementById("editor");
const codeMirrorInstance = CodeMirror.fromTextArea(myTextArea, {
readOnly: true,
lineNumbers: true,
lineWrapping: false,
mode: "text/typescript",
gutters: ["TS-lineuncovered", "CodeMirror-linenumbers"]
});
const annotations = JSON.parse(
document.getElementById("annotations").textContent
);
const gutters = {};

annotations.forEach((annotation) => {
gutters[annotation.line] = (gutters[annotation.line] || 0) + 1;
codeMirrorInstance.markText(
{ line: annotation.line, ch: annotation.character },
{
line: annotation.line,
ch: annotation.character + annotation.text.length
},
{
className: "uncovered"
}
);
});

Object.entries(gutters).forEach(([line, count]) => {
const gutterMarker = document.createElement("div");

gutterMarker.textContent = count + "x";
gutterMarker.classList.add("gutter-marker");
gutterMarker.style.background = "rgba(255,0,0," + count * 0.2 + ")";

codeMirrorInstance.setGutterMarker(+line, "TS-lineuncovered", gutterMarker);
});
});
Loading