Skip to content

Commit

Permalink
Merge branch 'main' into joao/add_steering_id_config
Browse files Browse the repository at this point in the history
  • Loading branch information
jpsantosbh committed Jan 30, 2024
2 parents 0ecc2f4 + d97c339 commit d759e36
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 18 deletions.
1 change: 1 addition & 0 deletions env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ SIGNALWIRE_PROJECT_KEY=YOURPROJECTKEY
SIGNALWIRE_TOKEN=YOURTOKEN
SIGNALWIRE_SPACE=YOURSPACE.signalwire.com
DEFAULT_DESTINATION=SOMETARGET
SIGNALWIRE_FABRIC_API_URL=https://fabric.swire.io/api

#Firebase Initilization Params
FIREBASE_API_KEY=<foo>
Expand Down
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const FIREBASE_CONFIG = JSON.stringify({
})

const host = process.env.RELAY_HOST
const fabricApiUrl = process.env.SIGNALWIRE_FABRIC_API_URL

async function apiRequest(uri, options) {
const response = await fetch(uri, options)
Expand Down Expand Up @@ -97,6 +98,7 @@ app.get('/', async (req, res) => {
res.render('index', {
host,
token: token,
fabricApiUrl: fabricApiUrl,
destination: process.env.DEFAULT_DESTINATION,
firebaseConfig: FIREBASE_CONFIG,
})
Expand All @@ -111,6 +113,7 @@ app.get('/minimal', async (req, res) => {
res.render('minimal', {
host,
token: token,
fabricApiUrl: fabricApiUrl,
destination: process.env.DEFAULT_DESTINATION,
firebaseConfig: FIREBASE_CONFIG,
})
Expand Down Expand Up @@ -164,7 +167,6 @@ app.post('/subscriber', async (req, res) => {
console.log('process subscriber')

const { reference, password } = req.body;
console.log("reference: ", reference, "password: ", password)

try {
const tokenData = await getSubscriberToken(reference, password)
Expand Down
27 changes: 16 additions & 11 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 109 additions & 4 deletions public/full.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const {
createMicrophoneAnalyzer,
} = SignalWire

const searchInput = document.getElementById('searchInput')
const searchType = document.getElementById('searchType')

window.getMicrophoneDevices = getMicrophoneDevices
window.getCameraDevices = getCameraDevices
window.getSpeakerDevices = getSpeakerDevices
Expand Down Expand Up @@ -878,6 +881,66 @@ const escapeHTML = (str) => {
return div.innerHTML
}

function isBlank(str) {
return str === null || str === undefined || str === '' || str === 'null';
}

function setupAddressModal() {
const addressModal = document.getElementById('addressModal')
if (!addressModal) return

addressModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget
const addressName = button.getAttribute('data-bs-name')
const address = __addressData.addresses.find(address => address.name === addressName)
updateAddressModal(address)

// TODO: load recent conversations associated with address
// messages = await fetchConversationHistory(__subscriberId, address.id)
// renderConversationHistory(messages)
})

addressModal.addEventListener('hidden.bs.modal', event => {
updateAddressModal({name:'',display_name:'',resouce_id:null,cover_url:null,preview_url:null,type:null,channels: []})
})
}

function updateAddressModal(address) {
const addressModal = document.getElementById('addressModal')
if (!addressModal) return

const addressDisplayName = addressModal.querySelector('.modal-body .address-display-name')
const addressAvatar = addressModal.querySelector('.modal-body .address-avatar')
const addressBadge = addressModal.querySelector('.modal-body .address-badge')
const channelButtons = {
audio: addressModal.querySelector('.modal-body .btn-address-dial-audio'),
video: addressModal.querySelector('.modal-body .btn-address-dial-video'),
messaging: addressModal.querySelector('.modal-body .btn-address-dial-messaging')
};

addressDisplayName.textContent = address.display_name
addressBadge.textContent = address.type
addressAvatar.src = address.cover_url || address.preview_url || `https://i.pravatar.cc/125?u=${address.resource_id}`

// disable all channel buttons
for (let channelButton in channelButtons) {
channelButtons[channelButton].disabled = true
}

// re-enable appropriate channel buttons
Object.entries(address.channels).forEach(([channelName, channelValue]) => {
let button = channelButtons[channelName]
let clone = button.cloneNode(true)
clone.disabled = false
button.parentNode.replaceChild(clone, button)
clone.addEventListener('click', () => {
dialAddress(channelValue)
const addressModalInstance = bootstrap.Modal.getInstance(addressModal)
addressModalInstance.hide()
})
})
}

function updateAddressUI() {
addressesCard.classList.remove('d-none')
const addressesDiv = document.getElementById('addresses')
Expand Down Expand Up @@ -913,9 +976,13 @@ function updateAddressUI() {
badge.textContent = type;
col1.appendChild(badge);

const b = document.createElement('b');
b.textContent = displayName;
col1.appendChild(b);
const addressNameLink = document.createElement('a');
addressNameLink.textContent = displayName;
addressNameLink.href = '#';
addressNameLink.dataset.bsToggle = 'modal';
addressNameLink.dataset.bsTarget = '#addressModal';
addressNameLink.dataset.bsName = address.name;
col1.appendChild(addressNameLink);

const col2 = document.createElement('div');
col2.className = 'col';
Expand Down Expand Up @@ -958,14 +1025,43 @@ function updateAddressUI() {
async function fetchAddresses() {
if (!client) return
try {
const addressData = await client.getAddresses()
const searchText = searchInput.value
const selectedType = searchType.value

const addressData = await client.getAddresses({
type: selectedType === 'all' ? undefined : selectedType,
displayName: !searchText.length ? undefined : searchText,
})
window.__addressData = addressData
updateAddressUI()
setupAddressModal()
} catch (error) {
console.error('Unable to fetch addresses', error)
}
}

// Just a placeholder until ready. We can prepare `client` methods as well
async function fetchConversationHistory(subscriberId, addressId) {
const queryParams = new URLSearchParams({
subscriber_id: subscriberId,
address_id: addressId,
limit: 10,
})

const response = await fetch(`${_fabricApiUrl}/conversations?${queryParams}`, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${_token}`
}
})

if (!response.ok) {
throw new Error('Unable to fetch conversation history')
}

return await response.json()
}

window.dialAddress = async (address) => {
const destinationInput = document.getElementById('destination')
destinationInput.value = address
Expand Down Expand Up @@ -993,3 +1089,12 @@ window.fetchPrevAddresses = async () => {
console.error('Unable to fetch prev addresses', error)
}
}

let debounceTimeout
searchInput.addEventListener('input', () => {
clearTimeout(debounceTimeout)
// Search after 1 seconds when user stops typing
debounceTimeout = setTimeout(fetchAddresses, 1000)
})

searchType.addEventListener('change', fetchAddresses)
111 changes: 109 additions & 2 deletions views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pako/2.1.0/pako.min.js"></script>

<!-- To style up the demo a little -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.min.css">

</head>
Expand Down Expand Up @@ -179,7 +179,29 @@
<div class="col-12 col-md-8 mt-4 mt-md-1">
<!-- Addresses -->
<div class="card" id="addressesCard">
<!-- Filters -->
<div class="input-group mt-1 px-2">
<input
type="text"
class="form-control"
placeholder="Search..."
aria-label="Search"
aria-describedby="searchButton"
id="searchInput"
/>
<select class="form-select" id="searchType">
<option value="all" selected>All</option>
<option value="subscriber">Subscriber</option>
<option value="room">Room</option>
<option value="call">Call</option>
<option value="app">App</option>
</select>
</div>
<!-- Filters end -->

<div class="card-body" id="addresses"></div>

<!-- Pagination -->
<div class="d-flex justify-content-center pb-2 gap-2">
<button
name="fetch-next-address"
Expand All @@ -196,6 +218,7 @@
Next
</button>
</div>
<!-- Pagination end -->
</div>
<!-- Addresses end -->

Expand Down Expand Up @@ -333,6 +356,88 @@
</div>
<hr />
</div>

<div class="modal fade" id="addressModal" tabindex="-1" aria-labelledby="addressModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-body">
<div class="container-fluid">

<div class="text-center address-info mt-3">
<div class="address-avatar-container">
<img src="https://i.pravatar.cc/[email protected]" alt="Avatar" class="rounded-circle avatar address-avatar">
</div>
<div class="row mt-1">
<div class="col-auto">
<span class="badge address-badge bg-primary me-2">
type
</span>
</div>
<div class="col-auto">
<h2 class="address-display-name">
First Last
</h2>
</div>
</div>
<div class="address-channels-buttons mt-3">
<button class="btn btn-secondary btn-address-dial-audio">
<i class="bi bi-phone"></i>
Call
</button>
<button class="btn btn-secondary btn-address-dial-video">
<i class="bi bi-camera-video"></i>
Video
</button>
<button class="btn btn-secondary btn-address-dial-messaging">
<i class="bi bi-chat"></i>
Chat
</button>
</div>
</div>

<div class="mt-4">
<h3 class="text-center">Recents</h3>
<div class="address-recent-messages">
<div class="address-recent-message shadow-sm p-2 mb-1 bg-body rounded">
<p class="card-text placeholder-glow">
<span class="placeholder placeholder-lg col-6"></span>
<span class="placeholder placeholder-lg col-12"></span>
</p>
</div>
<div class="address-recent-message shadow-sm p-2 mb-1 bg-body rounded">
<p class="card-text placeholder-glow">
<span class="placeholder placeholder-lg col-6"></span>
<span class="placeholder placeholder-lg col-12"></span>
</p>
</div>
<div class="address-recent-message shadow-sm p-2 mb-1 bg-body rounded">
<p class="card-text placeholder-glow">
<span class="placeholder placeholder-lg col-6"></span>
<span class="placeholder placeholder-lg col-12"></span>
</p>
</div>
<div class="address-recent-message shadow-sm p-2 mb-1 bg-body rounded">
<p class="card-text placeholder-glow">
<span class="placeholder placeholder-lg col-6"></span>
<span class="placeholder placeholder-lg col-12"></span>
</p>
</div>
<div class="address-recent-message shadow-sm p-2 mb-1 bg-body rounded">
<p class="card-text placeholder-glow">
<span class="placeholder placeholder-lg col-6"></span>
<span class="placeholder placeholder-lg col-12"></span>
</p>
</div>
</div>
</div>
</div>

</div>
</div>
</div>
</div>
</div>

<script type="module">
// Import Firebase libs
import { initializeApp } from 'https://www.gstatic.com/firebasejs/10.4.0/firebase-app.js'
Expand All @@ -348,8 +453,10 @@
<script type="text/javascript">
const _token = "<%= token %>";
const _host = "<%= host %>";
const _fabricApiUrl = "<%= fabricApiUrl %>";
const _firebaseConfig = <%- firebaseConfig %>;
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://unpkg.com/@signalwire/js@dev"></script>
<script src="/full.js"></script>
</body>
Expand Down
Loading

0 comments on commit d759e36

Please sign in to comment.