Skip to content

Commit 4f35b03

Browse files
Adding mq6 and nuxtbe.
1 parent 1804f5d commit 4f35b03

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+4461
-307
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
<template>
2+
<div>
3+
<h2>Real-time Messaging Interface</h2>
4+
5+
<!-- Subscription Management -->
6+
<div>
7+
<h3>Manage Subscriptions</h3>
8+
<UInput v-model="subscriptionName" placeholder="Enter topic or channel name"/>
9+
<UButton @click="subscribeToEvent">Subscribe</UButton>
10+
<UButton @click="unsubscribeFromEvent">Unsubscribe</UButton>
11+
</div>
12+
13+
<!-- Send Test Message -->
14+
<div>
15+
<h3>Send Test Message</h3>
16+
<UButton @click="sendTestMessage">Send Test Message</UButton>
17+
</div>
18+
19+
<!-- Publish Custom Message -->
20+
<div>
21+
<h3>Publish Custom Message</h3>
22+
<UInput v-model="customMessage.content" placeholder="Message content"/>
23+
<UInput v-model="customMessage.topic" placeholder="Topic (optional)"/>
24+
<UInput v-model="customMessage.channel" placeholder="Channel (optional)"/>
25+
<UInput v-model="customMessage.sender" placeholder="Sender (optional)"/>
26+
<UInput v-model="customMessage.routingKey" placeholder="Routing Key (optional)"/>
27+
<UButton @click="publishCustomMessage">Publish Message</UButton>
28+
</div>
29+
30+
<!-- Message Log Display -->
31+
<div>
32+
<h3>Messages</h3>
33+
<ul>
34+
<li v-for="msg in messages" :key="msg.id">
35+
<strong>{{ msg.event || msg.topic || msg.channel }}:</strong>
36+
<span>{{ msg.sender }} - {{ msg.content }}</span>
37+
</li>
38+
</ul>
39+
</div>
40+
</div>
41+
</template>
42+
43+
<script setup>
44+
import {ref} from 'vue';
45+
import {useMessageHandler} from '@/composables/useMessageHandler';
46+
47+
// Composable functions and data
48+
const {messages, sendTestMessage, publishMessage, subscribe, unsubscribe} = useMessageHandler();
49+
50+
// Local state for UI UInputs
51+
const subscriptionName = ref('');
52+
const customMessage = ref({
53+
content: '',
54+
topic: '',
55+
channel: '',
56+
sender: 'user',
57+
routingKey: 'default-slug',
58+
});
59+
60+
// Functions to handle user actions
61+
const subscribeToEvent = () => {
62+
if (subscriptionName.value) {
63+
subscribe(subscriptionName.value);
64+
console.log(`Subscribed to: ${subscriptionName.value}`);
65+
}
66+
};
67+
68+
const unsubscribeFromEvent = () => {
69+
if (subscriptionName.value) {
70+
unsubscribe(subscriptionName.value);
71+
console.log(`Unsubscribed from: ${subscriptionName.value}`);
72+
}
73+
};
74+
75+
const publishCustomMessage = () => {
76+
const messageInput = {
77+
content: customMessage.value.content,
78+
topic: customMessage.value.topic || undefined,
79+
channel: customMessage.value.channel || undefined,
80+
sender: customMessage.value.sender,
81+
routing_key: customMessage.value.routingKey,
82+
};
83+
publishMessage(messageInput).then(() => {
84+
console.log('Custom message published');
85+
});
86+
};
87+
</script>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!-- components/PublishMessage.vue -->
2+
<template>
3+
<div>
4+
<h2>Publish Message</h2>
5+
<input v-model="content" placeholder="Enter message content"/>
6+
<button @click="publishToHealth">Publish to Health Topic</button>
7+
<button @click="publishToEmailChannel">Publish to Email Channel</button>
8+
</div>
9+
</template>
10+
11+
<script setup>
12+
import {ref} from 'vue'
13+
import {useTopic} from '~/composables/useTopic'
14+
import {useChannel} from '~/composables/useChannel'
15+
16+
const content = ref('')
17+
18+
// Initialize composables
19+
const {sendMessage: sendToHealth} = useTopic('health')
20+
const {sendMessage: sendToEmailChannel} = useChannel('notification/email')
21+
22+
// Functions to publish messages
23+
const publishToHealth = () => {
24+
if (content.value.trim() === '') {
25+
alert('Please enter a message content.')
26+
return
27+
}
28+
sendToHealth(content.value)
29+
content.value = ''
30+
}
31+
32+
const publishToEmailChannel = () => {
33+
if (content.value.trim() === '') {
34+
alert('Please enter a message content.')
35+
return
36+
}
37+
sendToEmailChannel(content.value)
38+
content.value = ''
39+
}
40+
</script>
41+
42+
<style scoped>
43+
input {
44+
padding: 8px;
45+
margin-right: 8px;
46+
width: 300px;
47+
}
48+
49+
button {
50+
padding: 8px 16px;
51+
margin-right: 8px;
52+
}
53+
</style>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!-- components/ReceiveMessages.vue -->
2+
<template>
3+
<div>
4+
<h2>Received Messages</h2>
5+
<div v-if="healthMessages.length">
6+
<h3>Health Topic Messages:</h3>
7+
<ul>
8+
<li v-for="(msg, index) in healthMessages" :key="index">{{ msg.content }}</li>
9+
</ul>
10+
</div>
11+
<div v-if="emailMessages.length">
12+
<h3>Email Channel Messages:</h3>
13+
<ul>
14+
<li v-for="(msg, index) in emailMessages" :key="index">{{ msg.content }}</li>
15+
</ul>
16+
</div>
17+
<div v-if="!healthMessages.length && !emailMessages.length">
18+
<p>No messages received yet.</p>
19+
</div>
20+
</div>
21+
</template>
22+
23+
<script setup>
24+
import {useTopic} from '~/composables/useTopic'
25+
import {useChannel} from '~/composables/useChannel'
26+
27+
const {messages: healthMessages} = useTopic('health')
28+
const {messages: emailMessages} = useChannel('notification/email')
29+
</script>
30+
31+
<style scoped>
32+
h3 {
33+
margin-top: 20px;
34+
}
35+
36+
ul {
37+
list-style-type: disc;
38+
margin-left: 20px;
39+
}
40+
</style>

nuxtbe/app/composables/useChannel.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// composables/useChannel.js
2+
3+
import {ref, onMounted, onBeforeUnmount} from 'vue'
4+
import {useNuxtApp} from '#app'
5+
6+
export function useChannel(channelName) {
7+
const {$socket} = useNuxtApp()
8+
const messages = ref([])
9+
10+
/**
11+
* Send a message to the specified channel.
12+
* @param {any} content - The content of the message.
13+
*/
14+
const sendMessage = (content) => {
15+
if ($socket?.connected) {
16+
$socket.emit('publish', {content, channel: channelName})
17+
} else {
18+
console.warn('Socket not connected. Cannot send message.')
19+
}
20+
}
21+
22+
/**
23+
* Handle incoming messages from the channel.
24+
* @param {Object} data - The message data.
25+
*/
26+
const handleMessage = (data) => {
27+
messages.value.push(data)
28+
}
29+
30+
onMounted(() => {
31+
if ($socket) {
32+
$socket.on(channelName, handleMessage)
33+
}
34+
})
35+
36+
onBeforeUnmount(() => {
37+
if ($socket) {
38+
$socket.off(channelName, handleMessage)
39+
}
40+
})
41+
42+
return {
43+
sendMessage,
44+
messages,
45+
}
46+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import {ref, onMounted, onUnmounted} from "vue";
2+
import {io} from "socket.io-client"; // Import Socket.IO client for WebSocket support
3+
4+
export function useMessageHandler() {
5+
const messages = ref([]); // Reactive array to store incoming messages
6+
const socket = ref(null); // Socket.IO instance, initialized later
7+
const baseUrl = "http://localhost:8000"; // Backend URL, change if necessary
8+
9+
// Function to initialize WebSocket connection with Socket.IO
10+
const connectSocket = () => {
11+
console.log("Connecting to socket");
12+
// // Connect to backend WebSocket server at /socket.io with 'websocket' as the only transport
13+
socket.value = io(`${baseUrl}`, {
14+
// Ensure the path matches the server's configuration
15+
transports: ['websocket'], // Forces use of WebSocket protocol only
16+
});
17+
18+
// Listen for all events on WebSocket
19+
socket.value.onAny((event, msg) => {
20+
console.log(`Received event: ${event}, message: ${JSON.stringify(msg)}`);
21+
handleMessage(event, msg); // Handle each received event by passing it to handleMessage
22+
});
23+
24+
// Debugging: Log successful connection to WebSocket
25+
socket.value.on("connect", () =>
26+
console.log("Connected to WebSocket server")
27+
);
28+
29+
// Debugging: Log disconnection events
30+
socket.value.on("disconnect", () =>
31+
console.log("Disconnected from WebSocket server")
32+
);
33+
};
34+
35+
// Function to process and store incoming messages in the messages array
36+
const handleMessage = (event, msg) => {
37+
messages.value.push({...msg, event}); // Store message with event name for context
38+
console.log(`Message stored: ${JSON.stringify(msg)}`); // Log the stored message
39+
};
40+
41+
// Function to dynamically subscribe to specific topic or channel events
42+
const subscribe = (eventName) => {
43+
if (socket.value) {
44+
// Register event listener for specific topic or channel
45+
socket.value.on(eventName, (msg) => handleMessage(eventName, msg));
46+
console.log(`Subscribed to event: ${eventName}`); // Debugging: log subscription
47+
}
48+
};
49+
50+
// Function to unsubscribe from a specific topic or channel
51+
const unsubscribe = (eventName) => {
52+
if (socket.value) {
53+
// Remove event listener for specific topic or channel
54+
socket.value.off(eventName);
55+
console.log(`Unsubscribed from event: ${eventName}`); // Debugging: log unsubscription
56+
}
57+
};
58+
59+
// Function to send a test message using the /send_message endpoint
60+
const sendTestMessage = async () => {
61+
try {
62+
// Call the backend endpoint using $fetch with base URL
63+
const data = await $fetch("/send_message", {baseURL: baseUrl});
64+
console.log("Test message sent successfully:", data); // Debugging: log successful test message
65+
return data; // Return data for further use if needed
66+
} catch (error) {
67+
// Catch and log any errors during the request
68+
console.error("Error sending test message:", error);
69+
}
70+
};
71+
72+
// Function to publish a custom message using the /publish_message endpoint
73+
const publishMessage = async (messageInput) => {
74+
try {
75+
// Post custom message data to the backend
76+
const data = await $fetch("/publish_message", {
77+
baseURL: baseUrl,
78+
method: "POST", // Specify HTTP POST method for creating messages
79+
body: messageInput, // Pass messageInput data in request body
80+
});
81+
console.log("Custom message published successfully:", data); // Debugging: log successful publication
82+
return data; // Return response data
83+
} catch (error) {
84+
// Catch and log any errors during the request
85+
console.error("Error publishing custom message:", error);
86+
}
87+
};
88+
89+
// Automatically connect to WebSocket when component is mounted
90+
onMounted(() => connectSocket());
91+
92+
// Disconnect from WebSocket when component is unmounted to avoid memory leaks
93+
onUnmounted(() => {
94+
if (socket.value) {
95+
socket.value.disconnect(); // Disconnect from WebSocket
96+
console.log("WebSocket connection closed"); // Debugging: log disconnection
97+
}
98+
});
99+
100+
// Return reactive data and functions for use in the component
101+
return {
102+
messages, // Array of messages received from WebSocket
103+
sendTestMessage, // Function to send test message via HTTP endpoint
104+
publishMessage, // Function to publish custom message via HTTP endpoint
105+
subscribe, // Function to dynamically subscribe to topics/channels
106+
unsubscribe, // Function to unsubscribe from topics/channels
107+
};
108+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// // composables/useMessaging.js
2+
// import {ref, onMounted, onUnmounted, inject} from "vue";
3+
//
4+
// export function useMessaging() {
5+
// const messages = ref([]); // Reactive array for messages
6+
// const socket = inject("socket"); // Inject the socket plugin
7+
//
8+
// if (!socket) {
9+
// throw new Error("Socket plugin not available. Ensure the plugin is properly registered.");
10+
// }
11+
//
12+
// // Function to handle incoming messages
13+
// const handleIncomingMessage = (topic, message) => {
14+
// messages.value.push({topic, ...message});
15+
// console.log(`Received message on '${topic}':`, message);
16+
// };
17+
//
18+
// // Subscribe to topics
19+
// const subscribeToTopics = () => {
20+
// socket.subscribe("promotions", (msg) => handleIncomingMessage("promotions", msg));
21+
// socket.subscribe("limited-offers", (msg) => handleIncomingMessage("limited-offers", msg));
22+
// console.log("Subscribed to 'promotions' and 'limited-offers' topics");
23+
// };
24+
//
25+
// // Connect and subscribe on mount
26+
// onMounted(() => {
27+
// socket.connect(); // Ensure socket is connected
28+
// subscribeToTopics();
29+
// });
30+
//
31+
// // Disconnect on unmount
32+
// onUnmounted(() => {
33+
// socket.disconnect();
34+
// });
35+
//
36+
// return {
37+
// messages,
38+
// };
39+
// }

0 commit comments

Comments
 (0)