Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
7 changes: 6 additions & 1 deletion dashboard/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,12 @@
"messageId": "Message ID",
"error": "Error"
},
"sendFailed": "Failed to send message"
"sendFailed": "Failed to send message",
"copyGroupId": "Copy ID",
"copyGroupIdSuccessTitle": "Group ID Copied",
"copyGroupIdSuccessMessage": "The selected group ID was copied to the clipboard.",
"copyGroupIdFailedTitle": "Copy Failed",
"copyGroupIdFailedMessage": "Unable to copy the selected group ID. Please try again."
},
"infrastructure": {
"title": "Infrastructure",
Expand Down
7 changes: 6 additions & 1 deletion dashboard/src/i18n/locales/he.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,12 @@
"messageId": "מזהה הודעה",
"error": "שגיאה"
},
"sendFailed": "שליחת ההודעה נכשלה"
"sendFailed": "שליחת ההודעה נכשלה",
"copyGroupId": "העתק מזהה",
"copyGroupIdSuccessTitle": "המזהה הועתק",
"copyGroupIdSuccessMessage": "מזהה הקבוצה שנבחרה הועתק ללוח.",
"copyGroupIdFailedTitle": "העתקה נכשלה",
"copyGroupIdFailedMessage": "לא ניתן להעתיק את מזהה הקבוצה הנבחר. נסה שוב."
},
"infrastructure": {
"title": "תשתית",
Expand Down
5 changes: 5 additions & 0 deletions dashboard/src/pages/MessageTester.css
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@
cursor: not-allowed;
}

.copy-btn {
font-size: 0.7rem;
font-weight: 600;
}

.response-status {
display: flex;
align-items: center;
Expand Down
56 changes: 43 additions & 13 deletions dashboard/src/pages/MessageTester.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useDocumentTitle } from '../hooks/useDocumentTitle';
import { useRole } from '../hooks/useRole';
import { useSessionsQuery, useSessionGroupsQuery } from '../hooks/queries';
import { PageHeader } from '../components/PageHeader';
import { useToast } from '../components/Toast';
import './MessageTester.css';

interface ApiResponse {
Expand All @@ -32,6 +33,7 @@ export function MessageTester() {
const [mediaUrl, setMediaUrl] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [response, setResponse] = useState<ApiResponse | null>(null);
const toast = useToast();

const { data: groups = [], isLoading: loadingGroups } = useSessionGroupsQuery(
session,
Expand All @@ -53,6 +55,22 @@ export function MessageTester() {
}
}, [groups, selectedGroup, recipientType]);

const handleCopyGroupId = async () => {
if (!selectedGroup) return;

if (!navigator.clipboard?.writeText) {
toast.error(t('messageTester.copyGroupIdFailedTitle'), t('messageTester.copyGroupIdFailedMessage'));
return;
}

try {
await navigator.clipboard.writeText(selectedGroup);
toast.success(t('messageTester.copyGroupIdSuccessTitle'), t('messageTester.copyGroupIdSuccessMessage'));
} catch {
toast.error(t('messageTester.copyGroupIdFailedTitle'), t('messageTester.copyGroupIdFailedMessage'));
}
};

const handleSend = async () => {
const targetId = recipientType === 'group' ? selectedGroup : recipient;
if (!session || !targetId) return;
Expand Down Expand Up @@ -141,19 +159,31 @@ export function MessageTester() {
<label>{recipientType === 'group' ? t('messageTester.selectGroup') : t('messageTester.recipientPhone')}</label>
{recipientType === 'group' ? (
<>
<select
value={selectedGroup}
onChange={e => setSelectedGroup(e.target.value)}
disabled={loadingGroups || groups.length === 0}
>
{loadingGroups && <option value="">{t('messageTester.loadingGroups')}</option>}
{!loadingGroups && groups.length === 0 && <option value="">{t('messageTester.noGroupsFound')}</option>}
{groups.map(g => (
<option key={g.id} value={g.id}>
{g.name}
</option>
))}
</select>
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
<select
value={selectedGroup}
onChange={e => setSelectedGroup(e.target.value)}
disabled={loadingGroups || groups.length === 0}
>
{loadingGroups && <option value="">{t('messageTester.loadingGroups')}</option>}
{!loadingGroups && groups.length === 0 && <option value="">{t('messageTester.noGroupsFound')}</option>}
{groups.map(g => (
<option key={g.id} value={g.id}>
{g.name}
</option>
))}
</select>
{groups.length > 0 &&
<button
type="button"
className="copy-btn"
onClick={handleCopyGroupId}
disabled={!selectedGroup}
>
{t('messageTester.copyGroupId')}
</button>
}
</div>
<span className="hint">{t('messageTester.selectGroupHint')}</span>
</>
) : (
Expand Down