Initial commit: WordPress wp-content (themes, plugins, languages)
- Theme: momentry (custom theme with REST API routes) - Plugins: code-snippets (contains all API proxies) - Languages: zh_TW translations - Excludes: cache, backups, uploads, logs
This commit is contained in:
249
themes/momentry/assets/js/main.js
Normal file
249
themes/momentry/assets/js/main.js
Normal file
@@ -0,0 +1,249 @@
|
||||
(function($) {
|
||||
'use strict';
|
||||
|
||||
const MomentryPortal = {
|
||||
apiRoot: momentryApi.root,
|
||||
nonce: momentryApi.nonce,
|
||||
|
||||
init: function() {
|
||||
this.bindEvents();
|
||||
this.loadIdentities();
|
||||
},
|
||||
|
||||
bindEvents: function() {
|
||||
$(document).on('click', '.identity-card', this.showIdentityDetail.bind(this));
|
||||
$(document).on('click', '.angle-coverage-btn', this.showAngleCoverage.bind(this));
|
||||
$(document).on('click', '.body-actions-btn', this.showBodyActions.bind(this));
|
||||
},
|
||||
|
||||
request: function(endpoint, method, data) {
|
||||
return $.ajax({
|
||||
url: this.apiRoot + endpoint,
|
||||
method: method,
|
||||
data: data,
|
||||
beforeSend: function(xhr) {
|
||||
xhr.setRequestHeader('X-WP-Nonce', momentryApi.nonce);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
loadIdentities: function(page = 1) {
|
||||
const self = this;
|
||||
|
||||
this.request('momentry/v1/identities', 'GET', {page: page, per_page: 20})
|
||||
.done(function(response) {
|
||||
if (response.success) {
|
||||
self.renderIdentityList(response.data);
|
||||
self.renderPagination(response.pagination);
|
||||
}
|
||||
})
|
||||
.fail(function(error) {
|
||||
console.error('Failed to load identities:', error);
|
||||
$('.identity-list').html('<p class="error">Failed to load identities. Please try again.</p>');
|
||||
});
|
||||
},
|
||||
|
||||
renderIdentityList: function(identities) {
|
||||
const html = identities.map(function(identity) {
|
||||
return `
|
||||
<div class="identity-card" data-uuid="${identity.uuid}">
|
||||
<h3 class="identity-name">${identity.name}</h3>
|
||||
<div class="identity-meta">
|
||||
<span class="source badge">${identity.source}</span>
|
||||
<span class="references">${identity.total_references} vectors</span>
|
||||
</div>
|
||||
<div class="quality-score">
|
||||
<div class="score-bar" style="width: ${(identity.quality_avg || 0) * 100}%"></div>
|
||||
<span class="score-value">${((identity.quality_avg || 0) * 100).toFixed(1)}%</span>
|
||||
</div>
|
||||
${identity.trace_duration ? `
|
||||
<div class="trace-stats">
|
||||
<span class="duration">${identity.trace_duration}s</span>
|
||||
<span class="confidence">${(identity.trace_confidence * 100).toFixed(1)}% confidence</span>
|
||||
</div>
|
||||
` : ''}
|
||||
<div class="identity-actions">
|
||||
<button class="btn angle-coverage-btn" data-uuid="${identity.uuid}">
|
||||
Angle Coverage
|
||||
</button>
|
||||
<button class="btn body-actions-btn" data-uuid="${identity.uuid}">
|
||||
Body Actions
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
$('.identity-list').html(html);
|
||||
},
|
||||
|
||||
renderPagination: function(pagination) {
|
||||
const html = `
|
||||
<div class="pagination">
|
||||
<button class="btn prev" ${pagination.page === 1 ? 'disabled' : ''}>
|
||||
Previous
|
||||
</button>
|
||||
<span class="page-info">
|
||||
Page ${pagination.page} of ${pagination.total_pages}
|
||||
</span>
|
||||
<button class="btn next" ${pagination.page >= pagination.total_pages ? 'disabled' : ''}>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('.pagination-container').html(html);
|
||||
},
|
||||
|
||||
showIdentityDetail: function(e) {
|
||||
const uuid = $(e.currentTarget).data('uuid');
|
||||
const self = this;
|
||||
|
||||
this.request(`momentry/v1/identities/${uuid}`, 'GET')
|
||||
.done(function(response) {
|
||||
if (response.success) {
|
||||
self.renderIdentityDetail(response.data);
|
||||
}
|
||||
})
|
||||
.fail(function(error) {
|
||||
console.error('Failed to load identity detail:', error);
|
||||
});
|
||||
},
|
||||
|
||||
renderIdentityDetail: function(identity) {
|
||||
const html = `
|
||||
<div class="identity-detail-modal">
|
||||
<h2>${identity.name}</h2>
|
||||
<div class="detail-section">
|
||||
<h3>Reference Vectors</h3>
|
||||
<p>Total: ${identity.reference_vectors.total}</p>
|
||||
<p>Angles: ${identity.reference_vectors.angles.join(', ') || 'None'}</p>
|
||||
<p>Quality Avg: ${((identity.reference_vectors.quality_avg || 0) * 100).toFixed(1)}%</p>
|
||||
</div>
|
||||
${identity.trace_stats ? `
|
||||
<div class="detail-section">
|
||||
<h3>Trace Statistics</h3>
|
||||
<p>Duration: ${identity.trace_stats.duration_seconds}s</p>
|
||||
<p>Confidence: ${(identity.trace_stats.avg_confidence * 100).toFixed(1)}%</p>
|
||||
<p>Appearances: ${identity.trace_stats.total_appearances} frames</p>
|
||||
</div>
|
||||
` : ''}
|
||||
<button class="btn close-modal">Close</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('.modal-container').html(html).show();
|
||||
},
|
||||
|
||||
showAngleCoverage: function(e) {
|
||||
e.stopPropagation();
|
||||
const uuid = $(e.currentTarget).data('uuid');
|
||||
const self = this;
|
||||
|
||||
this.request(`momentry/v1/identities/${uuid}/angle-coverage`, 'GET')
|
||||
.done(function(response) {
|
||||
if (response.success) {
|
||||
self.renderAngleCoverage(response.data);
|
||||
}
|
||||
})
|
||||
.fail(function(error) {
|
||||
console.error('Failed to load angle coverage:', error);
|
||||
});
|
||||
},
|
||||
|
||||
renderAngleCoverage: function(data) {
|
||||
const angles = Object.entries(data.angles).map(function([angle, stats]) {
|
||||
const statusIcon = stats.status === 'dominant' ? '✅' :
|
||||
stats.status === 'present' ? '✅' : '⚠️';
|
||||
const count = stats.count > 0 ? `${stats.count} frames` : '0 frames';
|
||||
const quality = stats.quality_avg ? `(${(stats.quality_avg * 100).toFixed(1)}%)` : '';
|
||||
|
||||
return `
|
||||
<div class="angle-item ${stats.status}">
|
||||
<span class="status-icon">${statusIcon}</span>
|
||||
<span class="angle-name">${angle.replace('_', ' ')}</span>
|
||||
<span class="count">${count} ${quality}</span>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
const html = `
|
||||
<div class="angle-coverage-modal">
|
||||
<h2>Angle Coverage</h2>
|
||||
<div class="coverage-score">
|
||||
Coverage Score: ${data.score}%
|
||||
</div>
|
||||
<div class="angles-list">
|
||||
${angles}
|
||||
</div>
|
||||
<p class="recommendation">${data.recommendation}</p>
|
||||
<button class="btn close-modal">Close</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('.modal-container').html(html).show();
|
||||
},
|
||||
|
||||
showBodyActions: function(e) {
|
||||
e.stopPropagation();
|
||||
const uuid = $(e.currentTarget).data('uuid');
|
||||
const self = this;
|
||||
|
||||
this.request(`momentry/v1/identities/${uuid}/body-actions`, 'GET')
|
||||
.done(function(response) {
|
||||
if (response.success) {
|
||||
self.renderBodyActions(response.data);
|
||||
}
|
||||
})
|
||||
.fail(function(error) {
|
||||
console.error('Failed to load body actions:', error);
|
||||
});
|
||||
},
|
||||
|
||||
renderBodyActions: function(data) {
|
||||
const actions = Object.entries(data.actions || {}).map(function([category, items]) {
|
||||
const itemsHtml = items.map(function(item) {
|
||||
return `<span class="action-badge">${item.action}: ${item.count}</span>`;
|
||||
}).join('');
|
||||
|
||||
return `
|
||||
<div class="action-category">
|
||||
<h4>${category}</h4>
|
||||
<div class="action-list">${itemsHtml}</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
const html = `
|
||||
<div class="body-actions-modal">
|
||||
<h2>Body Actions: ${data.name}</h2>
|
||||
<div class="actions-container">
|
||||
${actions || '<p>No body actions detected</p>'}
|
||||
</div>
|
||||
<button class="btn close-modal">Close</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
$('.modal-container').html(html).show();
|
||||
},
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
MomentryPortal.init();
|
||||
|
||||
$(document).on('click', '.close-modal', function() {
|
||||
$('.modal-container').hide();
|
||||
});
|
||||
|
||||
$(document).on('click', '.pagination .prev:not([disabled])', function() {
|
||||
const page = parseInt($('.page-info').text().match(/Page (\d+)/)[1]);
|
||||
MomentryPortal.loadIdentities(page - 1);
|
||||
});
|
||||
|
||||
$(document).on('click', '.pagination .next:not([disabled])', function() {
|
||||
const page = parseInt($('.page-info').text().match(/Page (\d+)/)[1]);
|
||||
MomentryPortal.loadIdentities(page + 1);
|
||||
});
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user