collavre_slack 0.2.2 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/collavre_slack/slack_integration.css +33 -0
- data/app/controllers/collavre_slack/creatives/slack_integrations_controller.rb +11 -0
- data/app/javascript/collavre_slack.js +61 -4
- data/config/routes.rb +5 -1
- data/lib/collavre_slack/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 13a4005b2d4412089caa83e43e2be4868ce50aa024a77904e7644320d30a5cbb
|
|
4
|
+
data.tar.gz: c5a8501c5e9149b4648a10dc5eac2ede04451e0474cc0d59119f123b2d6763dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 82d93fd5f769a694bb3afc27246b75f161b8f5d50afd9a09e1f1939eb26f5e774c193e9b6a2ce4d04c0ac5faf088c13abb6d693afdd0080463bd4b5ccb1fa463
|
|
7
|
+
data.tar.gz: 9de647749fb26de533513da779f9726185781071129c28080568402b8f30fb3037694175c7bf91f007f25acc005f07f44fc1186f49d01b15f719409633fe1a2a
|
|
@@ -24,3 +24,36 @@
|
|
|
24
24
|
background: var(--color-drag-over);
|
|
25
25
|
border-left: 3px solid var(--color-secondary-active);
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
/* Slack badge in comments popup header */
|
|
29
|
+
.slack-channel-badge {
|
|
30
|
+
display: none;
|
|
31
|
+
font-size: 0.7em;
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
background: #4A154B;
|
|
34
|
+
color: white;
|
|
35
|
+
padding: 0.15em 0.45em;
|
|
36
|
+
border-radius: 4px;
|
|
37
|
+
margin-left: 0.5em;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
vertical-align: middle;
|
|
41
|
+
line-height: 1.4;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.slack-channel-badge:hover {
|
|
45
|
+
background: #611f64;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.slack-channel-tooltip {
|
|
49
|
+
display: none;
|
|
50
|
+
font-size: 0.75em;
|
|
51
|
+
color: var(--color-text-secondary);
|
|
52
|
+
margin-left: 0.4em;
|
|
53
|
+
white-space: nowrap;
|
|
54
|
+
vertical-align: middle;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.slack-channel-tooltip.visible {
|
|
58
|
+
display: inline;
|
|
59
|
+
}
|
|
@@ -60,6 +60,17 @@ module CollavreSlack
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
# Lightweight endpoint for badge display — returns only existing links, no Slack API calls
|
|
64
|
+
def badge
|
|
65
|
+
target_creative = @creative.effective_origin
|
|
66
|
+
links = SlackChannelLink.where(creative: target_creative)
|
|
67
|
+
render json: {
|
|
68
|
+
links: links.map { |link|
|
|
69
|
+
{ channel_name: link.channel_name }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
63
74
|
def destroy
|
|
64
75
|
link = SlackChannelLink.find(params[:id])
|
|
65
76
|
# Check against origin creative
|
|
@@ -487,35 +487,79 @@ if (!slackIntegrationInitialized) {
|
|
|
487
487
|
});
|
|
488
488
|
|
|
489
489
|
// Slack badge for comments popup
|
|
490
|
+
// Store references for cleanup to avoid handler accumulation across popup opens
|
|
491
|
+
let slackBadgeClickHandler = null;
|
|
492
|
+
let slackDocumentClickHandler = null;
|
|
493
|
+
let slackBadgeRequestId = 0; // Guard against stale async responses
|
|
494
|
+
|
|
490
495
|
document.addEventListener('comments-popup:opened', async function (event) {
|
|
491
496
|
const { creativeId, badgeContainer } = event.detail;
|
|
492
497
|
if (!badgeContainer || !creativeId) return;
|
|
493
498
|
|
|
499
|
+
// Increment request id to invalidate any in-flight fetch
|
|
500
|
+
const currentRequestId = ++slackBadgeRequestId;
|
|
501
|
+
|
|
494
502
|
// Create or find slack badge element
|
|
495
503
|
let badge = badgeContainer.querySelector('[data-slack-badge]');
|
|
496
504
|
if (!badge) {
|
|
497
505
|
badge = document.createElement('span');
|
|
498
506
|
badge.setAttribute('data-slack-badge', '');
|
|
499
507
|
badge.className = 'slack-channel-badge';
|
|
500
|
-
badge.style.cssText = 'display:none;font-size:0.75em;background:#4A154B;color:white;padding:0.15em 0.5em;border-radius:4px;margin-left:0.5em;';
|
|
501
508
|
badgeContainer.appendChild(badge);
|
|
502
509
|
}
|
|
503
510
|
|
|
511
|
+
// Clean up previous handlers before re-registering
|
|
512
|
+
if (slackBadgeClickHandler) {
|
|
513
|
+
badge.removeEventListener('click', slackBadgeClickHandler);
|
|
514
|
+
slackBadgeClickHandler = null;
|
|
515
|
+
}
|
|
516
|
+
if (slackDocumentClickHandler) {
|
|
517
|
+
document.removeEventListener('click', slackDocumentClickHandler);
|
|
518
|
+
slackDocumentClickHandler = null;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Remove any existing tooltip
|
|
522
|
+
const existingTooltip = badgeContainer.querySelector('[data-slack-tooltip]');
|
|
523
|
+
if (existingTooltip) existingTooltip.remove();
|
|
524
|
+
|
|
504
525
|
// Hide badge initially
|
|
505
526
|
badge.style.display = 'none';
|
|
506
527
|
badge.textContent = '';
|
|
507
528
|
|
|
508
529
|
try {
|
|
509
|
-
const response = await fetch(`/slack/creatives/${creativeId}/slack_integrations`, {
|
|
530
|
+
const response = await fetch(`/slack/creatives/${creativeId}/slack_integrations/badge`, {
|
|
510
531
|
headers: { Accept: 'application/json' }
|
|
511
532
|
});
|
|
533
|
+
|
|
534
|
+
// Discard response if a newer popup open has occurred
|
|
535
|
+
if (currentRequestId !== slackBadgeRequestId) return;
|
|
536
|
+
|
|
512
537
|
if (!response.ok) return;
|
|
513
538
|
|
|
514
539
|
const data = await response.json();
|
|
515
540
|
if (data.links && data.links.length > 0) {
|
|
516
|
-
|
|
517
|
-
badge.textContent = `Slack: ${channelNames}`;
|
|
541
|
+
badge.textContent = 'Slack';
|
|
518
542
|
badge.style.display = 'inline-block';
|
|
543
|
+
badge.title = data.links.map(link => `#${link.channel_name}`).join(', ');
|
|
544
|
+
|
|
545
|
+
// Create tooltip element for click display
|
|
546
|
+
const tooltip = document.createElement('span');
|
|
547
|
+
tooltip.setAttribute('data-slack-tooltip', '');
|
|
548
|
+
tooltip.className = 'slack-channel-tooltip';
|
|
549
|
+
tooltip.textContent = data.links.map(link => `#${link.channel_name}`).join(', ');
|
|
550
|
+
badgeContainer.appendChild(tooltip);
|
|
551
|
+
|
|
552
|
+
slackBadgeClickHandler = function (e) {
|
|
553
|
+
e.stopPropagation();
|
|
554
|
+
tooltip.classList.toggle('visible');
|
|
555
|
+
};
|
|
556
|
+
badge.addEventListener('click', slackBadgeClickHandler);
|
|
557
|
+
|
|
558
|
+
// Close tooltip when clicking elsewhere
|
|
559
|
+
slackDocumentClickHandler = function () {
|
|
560
|
+
tooltip.classList.remove('visible');
|
|
561
|
+
};
|
|
562
|
+
document.addEventListener('click', slackDocumentClickHandler);
|
|
519
563
|
}
|
|
520
564
|
} catch (error) {
|
|
521
565
|
console.warn('Failed to load Slack badge:', error);
|
|
@@ -526,10 +570,23 @@ if (!slackIntegrationInitialized) {
|
|
|
526
570
|
const { badgeContainer } = event.detail;
|
|
527
571
|
if (!badgeContainer) return;
|
|
528
572
|
|
|
573
|
+
// Invalidate any in-flight badge fetch so late responses are discarded
|
|
574
|
+
slackBadgeRequestId++;
|
|
575
|
+
|
|
529
576
|
const badge = badgeContainer.querySelector('[data-slack-badge]');
|
|
530
577
|
if (badge) {
|
|
531
578
|
badge.style.display = 'none';
|
|
532
579
|
badge.textContent = '';
|
|
580
|
+
if (slackBadgeClickHandler) {
|
|
581
|
+
badge.removeEventListener('click', slackBadgeClickHandler);
|
|
582
|
+
slackBadgeClickHandler = null;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
if (slackDocumentClickHandler) {
|
|
586
|
+
document.removeEventListener('click', slackDocumentClickHandler);
|
|
587
|
+
slackDocumentClickHandler = null;
|
|
533
588
|
}
|
|
589
|
+
const tooltip = badgeContainer.querySelector('[data-slack-tooltip]');
|
|
590
|
+
if (tooltip) tooltip.remove();
|
|
534
591
|
});
|
|
535
592
|
}
|
data/config/routes.rb
CHANGED
|
@@ -3,7 +3,11 @@ CollavreSlack::Engine.routes.draw do
|
|
|
3
3
|
get "/auth/slack/callback", to: "slack_auth#callback"
|
|
4
4
|
|
|
5
5
|
resources :creatives, only: [] do
|
|
6
|
-
resources :slack_integrations, module: :creatives, only: [ :index, :create, :destroy ]
|
|
6
|
+
resources :slack_integrations, module: :creatives, only: [ :index, :create, :destroy ] do
|
|
7
|
+
collection do
|
|
8
|
+
get :badge
|
|
9
|
+
end
|
|
10
|
+
end
|
|
7
11
|
resources :slack_messages, only: [ :create ]
|
|
8
12
|
end
|
|
9
13
|
|