Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
113 changes: 113 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@
<link href="styles.css" rel="stylesheet">
</head>
<body>
<div class="inbox-header">
<div class="inbox-icon-container" onclick="toggleInboxPanel()">
<svg class="inbox-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline>
<path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path>
</svg>
<span class="inbox-badge" id="inboxBadge" style="display: none;">0</span>
</div>
</div>
<div class="inbox-panel" id="inboxPanel" style="display: none;">
<div class="inbox-panel-header">
<h3>Inbox Messages</h3>
<button class="close-btn" onclick="toggleInboxPanel()">×</button>
</div>
<div class="inbox-panel-content" id="inboxPanelContent">
<p class="no-messages">No messages</p>
</div>
</div>
<div id="banner"></div>
<div class="row header">
<h1>Gist for Web</h1>
Expand Down Expand Up @@ -121,6 +139,101 @@ <h1>Gist for Web</h1>
function addAnonymousCustomAttribute() {
Gist.setCustomAttribute("cio_anonymous_id", "123456");
}

// Inbox functionality
async function updateInboxBadge() {
const messages = await Gist.getInboxMessages();
const unreadCount = messages.filter(msg => !msg.opened).length;
const badge = document.getElementById('inboxBadge');
if (unreadCount > 0) {
badge.textContent = unreadCount;
badge.style.display = 'inline-block';
} else {
badge.style.display = 'none';
}
}

async function toggleInboxPanel() {
const panel = document.getElementById('inboxPanel');
if (panel.style.display === 'none') {
panel.style.display = 'block';
await loadInboxMessages();
} else {
panel.style.display = 'none';
}
}

async function loadInboxMessages() {
const messages = await Gist.getInboxMessages();
const content = document.getElementById('inboxPanelContent');

if (messages.length === 0) {
content.innerHTML = '<p class="no-messages">No messages</p>';
return;
}

let html = '';
for (const message of messages) {
const isUnread = !message.opened;
const props = message.properties || {};
const queueId = message.queueId;
const propertiesJson = JSON.stringify(props, null, 2);

html += `
<div class="inbox-message ${isUnread ? 'unread' : ''}" data-queue-id="${queueId}">
<div class="inbox-message-header">
<strong>Properties</strong>
${isUnread ? '<span class="unread-dot"></span>' : ''}
</div>
<div class="inbox-message-body">
<pre>${propertiesJson}</pre>
</div>
<div class="inbox-message-actions">
${isUnread ? `<button onclick="markAsRead('${queueId}')">Mark as read</button>` : ''}
<button onclick="deleteMessage('${queueId}')">Delete</button>
</div>
</div>
`;
}

content.innerHTML = html;
}

async function markAsRead(queueId) {
try {
await Gist.markInboxMessageAsOpened(queueId);
await loadInboxMessages();
await updateInboxBadge();
} catch (error) {
console.error('Failed to mark message as read:', error);
alert('Failed to mark message as read. Please try again.');
}
}

async function deleteMessage(queueId) {
// Remove from UI immediately
const messageElement = document.querySelector(`[data-queue-id="${queueId}"]`);
if (messageElement) {
messageElement.remove();
}

// Update badge immediately
await updateInboxBadge();

try {
await Gist.removeInboxMessage(queueId);
} catch (error) {
console.error('Failed to delete message:', error);
alert('Failed to delete message. Please try again.');
// Reload messages to restore the UI state
await loadInboxMessages();
await updateInboxBadge();
}
}

// Update badge on load and periodically
updateInboxBadge();
setInterval(updateInboxBadge, 5000);
</script>
</body>
</html>
214 changes: 214 additions & 0 deletions examples/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ html, body {
line-height: 1.4;
}

body {
padding-top: 40px;
}

.row {
margin: 0px 16px;
display: flex;
Expand Down Expand Up @@ -52,4 +56,214 @@ h1 {
.button {
width: 100%;
}
}

/* Inbox Header */
.inbox-header {
height: 40px;
background-color: #e76f51;
display: flex;
align-items: center;
justify-content: flex-end;
padding: 0 16px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
}

.inbox-icon-container {
position: relative;
cursor: pointer;
padding: 8px;
border-radius: 4px;
transition: background-color 0.2s;
}

.inbox-icon-container:hover {
background-color: rgba(255,255,255,0.1);
}

.inbox-icon {
color: white;
display: block;
}

.inbox-badge {
position: absolute;
top: 2px;
right: 2px;
background-color: #264653;
color: white;
border-radius: 10px;
padding: 2px 6px;
font-size: 11px;
font-weight: bold;
min-width: 18px;
text-align: center;
}

/* Inbox Panel */
.inbox-panel {
position: fixed;
top: 40px;
right: 0;
width: 400px;
max-width: 100%;
max-height: calc(100vh - 40px);
background-color: white;
box-shadow: -2px 0 8px rgba(0,0,0,0.15);
z-index: 999;
overflow-y: auto;
display: flex;
flex-direction: column;
}

.inbox-panel .inbox-panel-content {
min-height: 400px;
}

.inbox-panel-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
border-bottom: 1px solid #e0e0e0;
background-color: #f5f5f5;
}

.inbox-panel-header h3 {
margin: 0;
font-size: 18px;
}

.close-btn {
background: none;
border: none;
font-size: 28px;
cursor: pointer;
color: #666;
padding: 0;
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
}

.close-btn:hover {
background-color: rgba(0,0,0,0.05);
}

.inbox-panel-content {
padding: 16px;
}

.no-messages {
text-align: center;
color: #999;
padding: 32px 16px;
font-size: 16px;
}

/* Inbox Message */
.inbox-message {
background-color: #fff;
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 16px;
margin-bottom: 12px;
transition: box-shadow 0.2s;
}

.inbox-message:hover {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.inbox-message.unread {
background-color: #f0f9ff;
border-color: #2a9d8f;
}

.inbox-message-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}

.inbox-message-header strong {
font-size: 16px;
color: #264653;
}

.unread-dot {
width: 8px;
height: 8px;
background-color: #2a9d8f;
border-radius: 50%;
display: inline-block;
margin-left: 8px;
}

.inbox-message-body {
font-size: 14px;
color: #555;
line-height: 1.5;
margin-bottom: 12px;
}

.inbox-message-body pre {
background-color: #f5f5f5;
padding: 12px;
border-radius: 4px;
overflow-x: auto;
font-size: 12px;
margin: 0;
font-family: 'Courier New', monospace;
}

.inbox-message-footer {
margin-bottom: 12px;
}

.inbox-message-footer a {
color: #2a9d8f;
text-decoration: none;
font-size: 14px;
font-weight: 600;
}

.inbox-message-footer a:hover {
text-decoration: underline;
}

.inbox-message-actions {
display: flex;
gap: 8px;
}

.inbox-message-actions button {
padding: 6px 12px;
font-size: 13px;
border: 1px solid #e0e0e0;
background-color: white;
color: #555;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}

.inbox-message-actions button:hover {
background-color: #f5f5f5;
border-color: #2a9d8f;
}

@media (max-width: 800px) {
.inbox-panel {
width: 100%;
}
}
19 changes: 19 additions & 0 deletions src/gist.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ import { showMessage, embedMessage, hideMessage, removePersistentMessage, fetchM
import { setUserLocale } from "./managers/locale-manager";
import { setCustomAttribute, clearCustomAttributes, removeCustomAttribute } from "./managers/custom-attribute-manager";
import { setupPreview } from "./utilities/preview-mode";
import {
getInboxMessagesFromLocalStore,
markInboxMessageAsOpened,
removeInboxMessage
} from "./managers/inbox-message-manager";

export default class {
static async setup(config) {
Expand Down Expand Up @@ -125,4 +130,18 @@ export default class {
this.events.dispatch('messageAction', {message: message, action: action, name: name});
}

// Inbox Messages

static async getInboxMessages() {
return await getInboxMessagesFromLocalStore();
}

static async markInboxMessageAsOpened(queueId) {
return await markInboxMessageAsOpened(queueId);
}

static async removeInboxMessage(queueId) {
return await removeInboxMessage(queueId);
}

}
Loading