fix test ask-AI oauth profile
This commit is contained in:
@ -79,7 +79,7 @@ a.view-markdown:any-link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header-content {
|
.header-content {
|
||||||
max-width: 1000px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr auto 1fr;
|
grid-template-columns: 1fr auto 1fr;
|
||||||
@ -197,7 +197,6 @@ a.view-markdown:any-link {
|
|||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Main Content */
|
|
||||||
.main-content {
|
.main-content {
|
||||||
grid-area: main;
|
grid-area: main;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
@ -206,13 +205,6 @@ a.view-markdown:any-link {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1000px) {
|
|
||||||
.main-content {
|
|
||||||
padding: 0px;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Timeline */
|
/* Timeline */
|
||||||
.timeline-container {
|
.timeline-container {
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
@ -327,12 +319,9 @@ a.view-markdown:any-link {
|
|||||||
|
|
||||||
/* Article */
|
/* Article */
|
||||||
.article-container {
|
.article-container {
|
||||||
display: grid;
|
max-width: 800px;
|
||||||
grid-template-columns: 1fr 240px;
|
|
||||||
/* gap: 40px; */
|
|
||||||
max-width: 1000px;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 100px 0;
|
padding: 100px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* article.article-content { padding: 10px; } */
|
/* article.article-content { padding: 10px; } */
|
||||||
@ -396,18 +385,12 @@ a.view-markdown:any-link {
|
|||||||
border-color: var(--white);
|
border-color: var(--white);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sidebar styles */
|
|
||||||
.article-sidebar {
|
|
||||||
position: sticky;
|
|
||||||
top: 100px;
|
|
||||||
height: fit-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toc {
|
.toc {
|
||||||
background: #f6f8fa;
|
background: #f6f8fa;
|
||||||
border: 1px solid #d1d9e0;
|
border: 1px solid #d1d9e0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc h3 {
|
.toc h3 {
|
||||||
@ -814,10 +797,8 @@ article.article-content {
|
|||||||
/* Responsive */
|
/* Responsive */
|
||||||
@media (max-width: 1000px) {
|
@media (max-width: 1000px) {
|
||||||
.article-container {
|
.article-container {
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 24px;
|
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
padding: 50px 0;
|
padding: 50px 20px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1141,7 +1122,66 @@ article.article-content {
|
|||||||
.article-meta {
|
.article-meta {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.article-actions {
|
.article-actions {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Loading spinner for Ask AI panel */
|
||||||
|
.loading-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-spinner {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border: 2px solid #f3f3f3;
|
||||||
|
border-top: 2px solid var(--theme-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-content p {
|
||||||
|
margin: 0;
|
||||||
|
color: #656d76;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle links in chat messages */
|
||||||
|
.message-header .handle a {
|
||||||
|
color: #656d76;
|
||||||
|
text-decoration: none;
|
||||||
|
transition: color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-header .handle a:hover {
|
||||||
|
color: var(--theme-color);
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1000px) {
|
||||||
|
.main-content {
|
||||||
|
padding: 0px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
article.article-content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.timeline-feed {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -12,24 +12,95 @@ function toggleAskAI() {
|
|||||||
panel.style.display = isVisible ? 'none' : 'block';
|
panel.style.display = isVisible ? 'none' : 'block';
|
||||||
|
|
||||||
if (!isVisible) {
|
if (!isVisible) {
|
||||||
checkAuthenticationStatus();
|
console.log('Ask AI panel opened');
|
||||||
|
|
||||||
|
// If AI profile data is already available, show introduction immediately
|
||||||
|
if (aiProfileData) {
|
||||||
|
console.log('AI profile data available - showing introduction immediately');
|
||||||
|
// Quick check for authentication
|
||||||
|
const userSections = document.querySelectorAll('.user-section');
|
||||||
|
const isAuthenticated = userSections.length > 0;
|
||||||
|
handleAuthenticationStatus(isAuthenticated);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For production fallback - if OAuth app fails to load, show profiles
|
||||||
|
const isProd = window.location.hostname !== 'localhost' && !window.location.hostname.includes('preview');
|
||||||
|
if (isProd) {
|
||||||
|
console.log('Production environment detected - using fallback profile display');
|
||||||
|
// Shorter timeout for production
|
||||||
|
setTimeout(() => {
|
||||||
|
const userSections = document.querySelectorAll('.user-section');
|
||||||
|
console.log('Production check - user sections:', userSections.length);
|
||||||
|
|
||||||
|
if (userSections.length === 0) {
|
||||||
|
console.log('No user sections found in production - showing profiles directly');
|
||||||
|
handleAuthenticationStatus(false);
|
||||||
|
} else {
|
||||||
|
console.log('User sections found in production - showing authenticated UI');
|
||||||
|
handleAuthenticationStatus(true);
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
} else {
|
||||||
|
checkAuthenticationStatus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAuthenticationStatus() {
|
function checkAuthenticationStatus() {
|
||||||
const userSections = document.querySelectorAll('.user-section');
|
// Check multiple times for OAuth app to load
|
||||||
const isAuthenticated = userSections.length > 0;
|
let checkCount = 0;
|
||||||
|
const maxChecks = 10;
|
||||||
|
|
||||||
|
const checkForAuth = () => {
|
||||||
|
console.log(`Auth check attempt ${checkCount + 1}/${maxChecks}`);
|
||||||
|
const userSections = document.querySelectorAll('.user-section');
|
||||||
|
const authButtons = document.querySelectorAll('[data-auth-status]');
|
||||||
|
const oauthContainers = document.querySelectorAll('#oauth-container');
|
||||||
|
|
||||||
|
console.log('User sections found:', userSections.length);
|
||||||
|
console.log('Auth buttons found:', authButtons.length);
|
||||||
|
console.log('OAuth containers found:', oauthContainers.length);
|
||||||
|
|
||||||
|
const isAuthenticated = userSections.length > 0;
|
||||||
|
|
||||||
|
if (isAuthenticated || checkCount >= maxChecks - 1) {
|
||||||
|
console.log('Final auth status:', isAuthenticated);
|
||||||
|
handleAuthenticationStatus(isAuthenticated);
|
||||||
|
} else {
|
||||||
|
checkCount++;
|
||||||
|
setTimeout(checkForAuth, 200);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkForAuth();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAuthenticationStatus(isAuthenticated) {
|
||||||
|
console.log('Handling auth status:', isAuthenticated);
|
||||||
|
|
||||||
|
// Always hide loading first
|
||||||
|
document.getElementById('authCheck').style.display = 'none';
|
||||||
|
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
// User is authenticated - show Ask AI UI
|
// User is authenticated - show Ask AI UI
|
||||||
document.getElementById('authCheck').style.display = 'none';
|
console.log('User authenticated - showing AI chat interface');
|
||||||
document.getElementById('chatForm').style.display = 'block';
|
document.getElementById('chatForm').style.display = 'block';
|
||||||
document.getElementById('chatHistory').style.display = 'block';
|
document.getElementById('chatHistory').style.display = 'block';
|
||||||
|
|
||||||
// Show initial greeting if chat history is empty
|
// Show initial greeting if chat history is empty and AI profile is available
|
||||||
const chatHistory = document.getElementById('chatHistory');
|
const chatHistory = document.getElementById('chatHistory');
|
||||||
if (chatHistory.children.length === 0) {
|
if (chatHistory.children.length === 0) {
|
||||||
showInitialGreeting();
|
if (aiProfileData) {
|
||||||
|
showInitialGreeting();
|
||||||
|
} else {
|
||||||
|
// Wait for AI profile data
|
||||||
|
setTimeout(() => {
|
||||||
|
if (aiProfileData) {
|
||||||
|
showInitialGreeting();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Focus on input
|
// Focus on input
|
||||||
@ -37,11 +108,18 @@ function checkAuthenticationStatus() {
|
|||||||
document.getElementById('aiQuestion').focus();
|
document.getElementById('aiQuestion').focus();
|
||||||
}, 50);
|
}, 50);
|
||||||
} else {
|
} else {
|
||||||
// User not authenticated - show profiles instead of auth message
|
// User not authenticated - show AI introduction directly if profile available
|
||||||
document.getElementById('authCheck').style.display = 'none';
|
console.log('User not authenticated - showing AI introduction');
|
||||||
document.getElementById('chatForm').style.display = 'none';
|
document.getElementById('chatForm').style.display = 'none';
|
||||||
document.getElementById('chatHistory').style.display = 'block';
|
document.getElementById('chatHistory').style.display = 'block';
|
||||||
loadAndShowProfiles();
|
|
||||||
|
if (aiProfileData) {
|
||||||
|
// Show AI introduction directly using available profile data
|
||||||
|
showAIIntroduction();
|
||||||
|
} else {
|
||||||
|
// Fallback to profile loading
|
||||||
|
loadAndShowProfiles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +174,7 @@ async function loadAndShowProfiles() {
|
|||||||
<div class="avatar">${avatarElement}</div>
|
<div class="avatar">${avatarElement}</div>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="display-name">${profile.value.author.displayName || profile.value.author.handle} ${adminBadge}</div>
|
<div class="display-name">${profile.value.author.displayName || profile.value.author.handle} ${adminBadge}</div>
|
||||||
<div class="handle">@${profile.value.author.handle}</div>
|
<div class="handle"><a href="https://web.syu.is/profile/${profile.value.author.handle}" target="_blank" rel="noopener noreferrer">@${profile.value.author.handle}</a></div>
|
||||||
<div class="timestamp">${new Date(profile.value.createdAt).toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">${profile.value.text}</div>
|
<div class="message-content">${profile.value.text}</div>
|
||||||
@ -178,8 +255,7 @@ function addUserMessage(question) {
|
|||||||
<div class="avatar">${userAvatar}</div>
|
<div class="avatar">${userAvatar}</div>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="display-name">${userDisplay}</div>
|
<div class="display-name">${userDisplay}</div>
|
||||||
<div class="handle">@${userHandle}</div>
|
<div class="handle"><a href="https://web.syu.is/profile/${userHandle}" target="_blank" rel="noopener noreferrer">@${userHandle}</a></div>
|
||||||
<div class="timestamp">${new Date().toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">${question}</div>
|
<div class="message-content">${question}</div>
|
||||||
@ -242,17 +318,57 @@ function showInitialGreeting() {
|
|||||||
<div class="avatar">${avatarElement}</div>
|
<div class="avatar">${avatarElement}</div>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="display-name">${aiProfileData.displayName}</div>
|
<div class="display-name">${aiProfileData.displayName}</div>
|
||||||
<div class="handle">@${aiProfileData.handle}</div>
|
<div class="handle"><a href="https://web.syu.is/profile/${aiProfileData.handle}" target="_blank" rel="noopener noreferrer">@${aiProfileData.handle}</a></div>
|
||||||
<div class="timestamp">${new Date().toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">
|
<div class="message-content">Hello! I'm an AI assistant trained on this blog's content. I can answer questions about the articles, provide insights, and help you understand the topics discussed here. What would you like to know?</div>
|
||||||
Hello! I'm an AI assistant trained on this blog's content. I can answer questions about the articles, provide insights, and help you understand the topics discussed here. What would you like to know?
|
|
||||||
</div>
|
|
||||||
`;
|
`;
|
||||||
chatHistory.appendChild(greetingDiv);
|
chatHistory.appendChild(greetingDiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showAIIntroduction() {
|
||||||
|
if (!aiProfileData) return;
|
||||||
|
|
||||||
|
const chatHistory = document.getElementById('chatHistory');
|
||||||
|
chatHistory.innerHTML = ''; // Clear any existing content
|
||||||
|
|
||||||
|
// AI Introduction message
|
||||||
|
const introDiv = document.createElement('div');
|
||||||
|
introDiv.className = 'chat-message ai-message comment-style initial-greeting';
|
||||||
|
|
||||||
|
const avatarElement = aiProfileData.avatar
|
||||||
|
? `<img src="${aiProfileData.avatar}" alt="${aiProfileData.displayName}" class="profile-avatar">`
|
||||||
|
: '🤖';
|
||||||
|
|
||||||
|
introDiv.innerHTML = `
|
||||||
|
<div class="message-header">
|
||||||
|
<div class="avatar">${avatarElement}</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="display-name">${aiProfileData.displayName}</div>
|
||||||
|
<div class="handle"><a href="https://web.syu.is/profile/${aiProfileData.handle}" target="_blank" rel="noopener noreferrer">@${aiProfileData.handle}</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="message-content">Hello! I'm an AI assistant trained on this blog's content. I can answer questions about the articles, provide insights, and help you understand the topics discussed here. What would you like to know?</div>
|
||||||
|
`;
|
||||||
|
chatHistory.appendChild(introDiv);
|
||||||
|
|
||||||
|
// OAuth login message
|
||||||
|
const loginDiv = document.createElement('div');
|
||||||
|
loginDiv.className = 'chat-message user-message comment-style initial-greeting';
|
||||||
|
|
||||||
|
loginDiv.innerHTML = `
|
||||||
|
<div class="message-header">
|
||||||
|
<div class="avatar">${avatarElement}</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<div class="display-name">${aiProfileData.displayName}</div>
|
||||||
|
<div class="handle"><a href="https://web.syu.is/profile/${aiProfileData.handle}" target="_blank" rel="noopener noreferrer">@${aiProfileData.handle}</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="message-content">Please atproto oauth login</div>
|
||||||
|
`;
|
||||||
|
chatHistory.appendChild(loginDiv);
|
||||||
|
}
|
||||||
|
|
||||||
function updateAskAIButton() {
|
function updateAskAIButton() {
|
||||||
const button = document.getElementById('askAiButton');
|
const button = document.getElementById('askAiButton');
|
||||||
if (!button) return;
|
if (!button) return;
|
||||||
@ -288,8 +404,7 @@ function handleAIResponse(responseData) {
|
|||||||
<div class="avatar">${avatarElement}</div>
|
<div class="avatar">${avatarElement}</div>
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<div class="display-name">${aiProfile.displayName}</div>
|
<div class="display-name">${aiProfile.displayName}</div>
|
||||||
<div class="handle">@${aiProfile.handle}</div>
|
<div class="handle"><a href="https://web.syu.is/profile/${aiProfile.handle}" target="_blank" rel="noopener noreferrer">@${aiProfile.handle}</a></div>
|
||||||
<div class="timestamp">${timestamp.toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-content">${responseData.answer}</div>
|
<div class="message-content">${responseData.answer}</div>
|
||||||
@ -377,6 +492,37 @@ function setupAskAIEventListeners() {
|
|||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
setupAskAIEventListeners();
|
setupAskAIEventListeners();
|
||||||
console.log('Ask AI initialized successfully');
|
console.log('Ask AI initialized successfully');
|
||||||
|
|
||||||
|
// Also listen for OAuth app load completion
|
||||||
|
const observer = new MutationObserver(function(mutations) {
|
||||||
|
mutations.forEach(function(mutation) {
|
||||||
|
if (mutation.type === 'childList') {
|
||||||
|
// Check if user-section was added/removed
|
||||||
|
const userSectionAdded = Array.from(mutation.addedNodes).some(node =>
|
||||||
|
node.nodeType === Node.ELEMENT_NODE &&
|
||||||
|
(node.classList?.contains('user-section') || node.querySelector?.('.user-section'))
|
||||||
|
);
|
||||||
|
const userSectionRemoved = Array.from(mutation.removedNodes).some(node =>
|
||||||
|
node.nodeType === Node.ELEMENT_NODE &&
|
||||||
|
(node.classList?.contains('user-section') || node.querySelector?.('.user-section'))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (userSectionAdded || userSectionRemoved) {
|
||||||
|
console.log('User section status changed');
|
||||||
|
// Update Ask AI panel if it's visible
|
||||||
|
const panel = document.getElementById('askAiPanel');
|
||||||
|
if (panel && panel.style.display !== 'none') {
|
||||||
|
checkAuthenticationStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Global functions for onclick handlers
|
// Global functions for onclick handlers
|
||||||
|
@ -61,7 +61,10 @@
|
|||||||
<div class="ask-ai-panel" id="askAiPanel" style="display: none;">
|
<div class="ask-ai-panel" id="askAiPanel" style="display: none;">
|
||||||
<div class="ask-ai-content">
|
<div class="ask-ai-content">
|
||||||
<div id="authCheck" class="auth-check">
|
<div id="authCheck" class="auth-check">
|
||||||
<p>profile</p>
|
<div class="loading-content">
|
||||||
|
<div class="loading-spinner"></div>
|
||||||
|
<p>Loading...</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="chatForm" class="ask-ai-form" style="display: none;">
|
<div id="chatForm" class="ask-ai-form" style="display: none;">
|
||||||
|
@ -27,21 +27,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div class="article-body">
|
|
||||||
{{ post.content | safe }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="comment-atproto"></div>
|
|
||||||
</article>
|
|
||||||
|
|
||||||
<aside class="article-sidebar">
|
|
||||||
<nav class="toc">
|
<nav class="toc">
|
||||||
<h3>Contents</h3>
|
<h3>Contents</h3>
|
||||||
<div id="toc-content">
|
<div id="toc-content">
|
||||||
<!-- TOC will be generated by JavaScript -->
|
<!-- TOC will be generated by JavaScript -->
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</aside>
|
|
||||||
|
<div class="article-body">
|
||||||
|
{{ post.content | safe }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="comment-atproto"></div>
|
||||||
|
</article>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -139,7 +139,7 @@ body {
|
|||||||
/* align-items: center; */
|
/* align-items: center; */
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 45px 0;
|
padding: 25px 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,6 +1070,10 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
article.article-content {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Avatar Styles */
|
/* Avatar Styles */
|
||||||
|
@ -69,8 +69,6 @@ export default function ChatRecordList({ chatPairs, apiConfig, user = null, agen
|
|||||||
)}
|
)}
|
||||||
<div className="user-info">
|
<div className="user-info">
|
||||||
<div className="display-name">{chatPair.question.value.author?.displayName || chatPair.question.value.author?.handle}</div>
|
<div className="display-name">{chatPair.question.value.author?.displayName || chatPair.question.value.author?.handle}</div>
|
||||||
<div className="handle">@{chatPair.question.value.author?.handle}</div>
|
|
||||||
<div className="timestamp">{new Date(chatPair.question.value.createdAt).toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
{canDelete(chatPair) && (
|
{canDelete(chatPair) && (
|
||||||
<div className="record-actions">
|
<div className="record-actions">
|
||||||
@ -105,8 +103,6 @@ export default function ChatRecordList({ chatPairs, apiConfig, user = null, agen
|
|||||||
)}
|
)}
|
||||||
<div className="user-info">
|
<div className="user-info">
|
||||||
<div className="display-name">{chatPair.answer.value.author?.displayName || chatPair.answer.value.author?.handle}</div>
|
<div className="display-name">{chatPair.answer.value.author?.displayName || chatPair.answer.value.author?.handle}</div>
|
||||||
<div className="handle">@{chatPair.answer.value.author?.handle}</div>
|
|
||||||
<div className="timestamp">{new Date(chatPair.answer.value.createdAt).toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="message-content">{chatPair.answer.value.text}</div>
|
<div className="message-content">{chatPair.answer.value.text}</div>
|
||||||
|
@ -58,8 +58,6 @@ export default function ProfileRecordList({ profileRecords, apiConfig, user = nu
|
|||||||
<span className="admin-badge"> Admin</span>
|
<span className="admin-badge"> Admin</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="handle">@{profile.value.author?.handle}</div>
|
|
||||||
<div className="timestamp">{new Date(profile.value.createdAt).toLocaleString()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
{canDelete(profile) && (
|
{canDelete(profile) && (
|
||||||
<div className="record-actions">
|
<div className="record-actions">
|
||||||
|
@ -64,18 +64,18 @@ export default function RecordTabs({ langRecords, commentRecords, userComments,
|
|||||||
>
|
>
|
||||||
chat ({userChatRecords?.length || 0})
|
chat ({userChatRecords?.length || 0})
|
||||||
</button>
|
</button>
|
||||||
<button
|
|
||||||
className={`tab-btn ${activeTab === 'users' ? 'active' : ''}`}
|
|
||||||
onClick={() => setActiveTab('users')}
|
|
||||||
>
|
|
||||||
comment ({filteredUserComments.length})
|
|
||||||
</button>
|
|
||||||
<button
|
<button
|
||||||
className={`tab-btn ${activeTab === 'comment' ? 'active' : ''}`}
|
className={`tab-btn ${activeTab === 'comment' ? 'active' : ''}`}
|
||||||
onClick={() => setActiveTab('comment')}
|
onClick={() => setActiveTab('comment')}
|
||||||
>
|
>
|
||||||
feedback ({filteredCommentRecords.length})
|
feedback ({filteredCommentRecords.length})
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
className={`tab-btn ${activeTab === 'users' ? 'active' : ''}`}
|
||||||
|
onClick={() => setActiveTab('users')}
|
||||||
|
>
|
||||||
|
comment ({filteredUserComments.length})
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
className={`tab-btn ${activeTab === 'lang' ? 'active' : ''}`}
|
className={`tab-btn ${activeTab === 'lang' ? 'active' : ''}`}
|
||||||
onClick={() => setActiveTab('lang')}
|
onClick={() => setActiveTab('lang')}
|
||||||
|
Reference in New Issue
Block a user