auto-claude: subtask-5-3 - Add collaboration matrix section showing company p
Added collaboration matrix section to IT audit dashboard with: - CSS styles for match type cards following combo-grid pattern - Six match type categories: M365 licensing, backup replication, Teams federation, shared monitoring, collective purchasing, and knowledge sharing - Company pairs display with status badges (suggested, contacted, active, declined) - Empty state with friendly message when no matches exist - Responsive grid layout matching social_media.html patterns Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
b9ba00fae9
commit
aab2b298a7
@ -3,7 +3,7 @@
|
||||
"spec": "001-audyt-it",
|
||||
"state": "building",
|
||||
"subtasks": {
|
||||
"completed": 17,
|
||||
"completed": 18,
|
||||
"total": 28,
|
||||
"in_progress": 1,
|
||||
"failed": 0
|
||||
@ -18,8 +18,8 @@
|
||||
"max": 1
|
||||
},
|
||||
"session": {
|
||||
"number": 18,
|
||||
"number": 19,
|
||||
"started_at": "2026-01-09T08:11:54.054044"
|
||||
},
|
||||
"last_update": "2026-01-09T09:00:29.741214"
|
||||
"last_update": "2026-01-09T09:03:14.642451"
|
||||
}
|
||||
@ -249,6 +249,129 @@
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
/* Collaboration Matrix */
|
||||
.collab-matrix-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: var(--spacing-lg);
|
||||
}
|
||||
|
||||
.match-type-card {
|
||||
background: var(--background);
|
||||
border-radius: var(--radius);
|
||||
padding: var(--spacing-md);
|
||||
}
|
||||
|
||||
.match-type-card h3 {
|
||||
font-size: var(--font-size-base);
|
||||
color: var(--text-primary);
|
||||
margin-bottom: var(--spacing-sm);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.match-type-card h3 .count {
|
||||
background: var(--primary);
|
||||
color: white;
|
||||
padding: 2px 8px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.match-type-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: var(--radius-sm);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: var(--spacing-xs);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.match-type-icon.m365 { background: #fff3e0; color: #d83b01; }
|
||||
.match-type-icon.backup { background: #e8f5e9; color: #2e7d32; }
|
||||
.match-type-icon.teams { background: #e8f4fc; color: #0078d4; }
|
||||
.match-type-icon.monitoring { background: #fee2e2; color: #dc2626; }
|
||||
.match-type-icon.purchasing { background: #f3e8ff; color: #7c3aed; }
|
||||
.match-type-icon.knowledge { background: #fef3c7; color: #92400e; }
|
||||
|
||||
.match-pairs-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.match-pair {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: var(--spacing-xs) 0;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.match-pair:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.match-pair-companies {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-xs);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.match-pair-companies a {
|
||||
color: var(--text-secondary);
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.match-pair-companies a:hover {
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.match-pair-separator {
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-size-xs);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.match-status-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 6px;
|
||||
border-radius: var(--radius-sm);
|
||||
font-size: var(--font-size-xs);
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
margin-left: var(--spacing-xs);
|
||||
}
|
||||
|
||||
.match-status-badge.suggested {
|
||||
background: #e0f2fe;
|
||||
color: #0284c7;
|
||||
}
|
||||
|
||||
.match-status-badge.contacted {
|
||||
background: #fef3c7;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
.match-status-badge.active {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.match-status-badge.declined {
|
||||
background: #fee2e2;
|
||||
color: #991b1b;
|
||||
}
|
||||
|
||||
/* Empty state */
|
||||
.empty-state {
|
||||
text-align: center;
|
||||
@ -856,6 +979,202 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Collaboration Matrix -->
|
||||
<div class="section">
|
||||
<h2>Macierz wspolpracy</h2>
|
||||
{% if collaboration_matches %}
|
||||
<div class="collab-matrix-grid">
|
||||
<!-- Shared M365 Licensing -->
|
||||
{% set m365_matches = collaboration_matches|selectattr('match_type', 'equalto', 'shared_m365_licensing')|list %}
|
||||
{% if m365_matches %}
|
||||
<div class="match-type-card">
|
||||
<h3>
|
||||
<span>
|
||||
<span class="match-type-icon m365">
|
||||
<svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M11.5 2.25L2.25 6v12l9.25 3.75L21.75 18V6L11.5 2.25z"/>
|
||||
</svg>
|
||||
</span>
|
||||
Wspoldzielone licencje M365
|
||||
</span>
|
||||
<span class="count">{{ m365_matches|length }}</span>
|
||||
</h3>
|
||||
<div class="match-pairs-list">
|
||||
{% for match in m365_matches %}
|
||||
<div class="match-pair">
|
||||
<div class="match-pair-companies">
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_a_id) }}" title="{{ match.company_a_name }}">{{ match.company_a_name }}</a>
|
||||
<span class="match-pair-separator">⟷</span>
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_b_id) }}" title="{{ match.company_b_name }}">{{ match.company_b_name }}</a>
|
||||
</div>
|
||||
<span class="match-status-badge {{ match.status }}">{{ match.status }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Backup Replication -->
|
||||
{% set backup_matches = collaboration_matches|selectattr('match_type', 'equalto', 'backup_replication')|list %}
|
||||
{% if backup_matches %}
|
||||
<div class="match-type-card">
|
||||
<h3>
|
||||
<span>
|
||||
<span class="match-type-icon backup">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4"/>
|
||||
</svg>
|
||||
</span>
|
||||
Replikacja backupow
|
||||
</span>
|
||||
<span class="count">{{ backup_matches|length }}</span>
|
||||
</h3>
|
||||
<div class="match-pairs-list">
|
||||
{% for match in backup_matches %}
|
||||
<div class="match-pair">
|
||||
<div class="match-pair-companies">
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_a_id) }}" title="{{ match.company_a_name }}">{{ match.company_a_name }}</a>
|
||||
<span class="match-pair-separator">⟷</span>
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_b_id) }}" title="{{ match.company_b_name }}">{{ match.company_b_name }}</a>
|
||||
</div>
|
||||
<span class="match-status-badge {{ match.status }}">{{ match.status }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Teams Federation -->
|
||||
{% set teams_matches = collaboration_matches|selectattr('match_type', 'equalto', 'teams_federation')|list %}
|
||||
{% if teams_matches %}
|
||||
<div class="match-type-card">
|
||||
<h3>
|
||||
<span>
|
||||
<span class="match-type-icon teams">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0z"/>
|
||||
</svg>
|
||||
</span>
|
||||
Federacja Teams
|
||||
</span>
|
||||
<span class="count">{{ teams_matches|length }}</span>
|
||||
</h3>
|
||||
<div class="match-pairs-list">
|
||||
{% for match in teams_matches %}
|
||||
<div class="match-pair">
|
||||
<div class="match-pair-companies">
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_a_id) }}" title="{{ match.company_a_name }}">{{ match.company_a_name }}</a>
|
||||
<span class="match-pair-separator">⟷</span>
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_b_id) }}" title="{{ match.company_b_name }}">{{ match.company_b_name }}</a>
|
||||
</div>
|
||||
<span class="match-status-badge {{ match.status }}">{{ match.status }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Shared Monitoring -->
|
||||
{% set monitoring_matches = collaboration_matches|selectattr('match_type', 'equalto', 'shared_monitoring')|list %}
|
||||
{% if monitoring_matches %}
|
||||
<div class="match-type-card">
|
||||
<h3>
|
||||
<span>
|
||||
<span class="match-type-icon monitoring">
|
||||
<svg width="16" height="16" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M3 3v18h18V3H3zm16 16H5V5h14v14zM7 7h2v2H7V7zm4 0h2v2h-2V7zm4 0h2v2h-2V7z"/>
|
||||
</svg>
|
||||
</span>
|
||||
Wspolny monitoring
|
||||
</span>
|
||||
<span class="count">{{ monitoring_matches|length }}</span>
|
||||
</h3>
|
||||
<div class="match-pairs-list">
|
||||
{% for match in monitoring_matches %}
|
||||
<div class="match-pair">
|
||||
<div class="match-pair-companies">
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_a_id) }}" title="{{ match.company_a_name }}">{{ match.company_a_name }}</a>
|
||||
<span class="match-pair-separator">⟷</span>
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_b_id) }}" title="{{ match.company_b_name }}">{{ match.company_b_name }}</a>
|
||||
</div>
|
||||
<span class="match-status-badge {{ match.status }}">{{ match.status }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Collective Purchasing -->
|
||||
{% set purchasing_matches = collaboration_matches|selectattr('match_type', 'equalto', 'collective_purchasing')|list %}
|
||||
{% if purchasing_matches %}
|
||||
<div class="match-type-card">
|
||||
<h3>
|
||||
<span>
|
||||
<span class="match-type-icon purchasing">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"/>
|
||||
</svg>
|
||||
</span>
|
||||
Zakupy grupowe
|
||||
</span>
|
||||
<span class="count">{{ purchasing_matches|length }}</span>
|
||||
</h3>
|
||||
<div class="match-pairs-list">
|
||||
{% for match in purchasing_matches %}
|
||||
<div class="match-pair">
|
||||
<div class="match-pair-companies">
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_a_id) }}" title="{{ match.company_a_name }}">{{ match.company_a_name }}</a>
|
||||
<span class="match-pair-separator">⟷</span>
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_b_id) }}" title="{{ match.company_b_name }}">{{ match.company_b_name }}</a>
|
||||
</div>
|
||||
<span class="match-status-badge {{ match.status }}">{{ match.status }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Knowledge Sharing -->
|
||||
{% set knowledge_matches = collaboration_matches|selectattr('match_type', 'equalto', 'knowledge_sharing')|list %}
|
||||
{% if knowledge_matches %}
|
||||
<div class="match-type-card">
|
||||
<h3>
|
||||
<span>
|
||||
<span class="match-type-icon knowledge">
|
||||
<svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"/>
|
||||
</svg>
|
||||
</span>
|
||||
Wymiana wiedzy
|
||||
</span>
|
||||
<span class="count">{{ knowledge_matches|length }}</span>
|
||||
</h3>
|
||||
<div class="match-pairs-list">
|
||||
{% for match in knowledge_matches %}
|
||||
<div class="match-pair">
|
||||
<div class="match-pair-companies">
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_a_id) }}" title="{{ match.company_a_name }}">{{ match.company_a_name }}</a>
|
||||
<span class="match-pair-separator">⟷</span>
|
||||
<a href="{{ url_for('company_detail', company_id=match.company_b_id) }}" title="{{ match.company_b_name }}">{{ match.company_b_name }}</a>
|
||||
</div>
|
||||
<span class="match-status-badge {{ match.status }}">{{ match.status }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<svg width="64" height="64" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1"/>
|
||||
</svg>
|
||||
<h3>Brak dopasowan wspolpracy</h3>
|
||||
<p>Dopasowania pojawia sie automatycznie, gdy firmy z podobna infrastruktura IT wypelnia audyty.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Company Audit Table -->
|
||||
<div class="section">
|
||||
<h2>Lista firm</h2>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user