feat: 대시보드 바로가기 새 탭 열기 + 탭 새로고침 시각 피드백
- 업무 현황의 "자주 가는 화면"·"최근 방문 메뉴"·메뉴검색 결과 클릭 시 워크스페이스 새 탭으로 열기(부모 wsOpenTab 호출, 밖이면 화면 이동 폴백) - 탭 새로고침(↻): 아이콘 회전 + 화면 잠깐 페이드 후 복구로 새로고침 확인 가능하게 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -129,7 +129,7 @@ $donutCss = $donutStops !== [] ? implode(', ', $donutStops) : '#e5e7eb 0% 100%';
|
||||
}
|
||||
var html = '<p class="text-[11px] text-white/70 mb-1.5"><i class="fa-regular fa-clock mr-1"></i>최근 방문 메뉴</p>';
|
||||
r.forEach(function (m) {
|
||||
html += '<a href="' + m.url + '" class="block text-[12px] px-2 py-1.5 rounded bg-white/12 hover:bg-white/25 mb-1 truncate" title="' + esc(m.name) + '">' + esc(m.name) +
|
||||
html += '<a href="' + m.url + '" data-title="' + esc(m.name) + '" class="js-tab-link block text-[12px] px-2 py-1.5 rounded bg-white/12 hover:bg-white/25 mb-1 truncate" title="' + esc(m.name) + '">' + esc(m.name) +
|
||||
(m.parent ? ' <span class="text-white/55">· ' + esc(m.parent) + '</span>' : '') + '</a>';
|
||||
});
|
||||
box.innerHTML = html;
|
||||
@@ -160,7 +160,28 @@ $donutCss = $donutStops !== [] ? implode(', ', $donutStops) : '#e5e7eb 0% 100%';
|
||||
list.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function go(url) { if (url) window.location.href = url; }
|
||||
// 워크스페이스(부모) 안이면 새 탭으로 열기, 아니면 현재 화면 이동
|
||||
function openInTab(url, name) {
|
||||
try {
|
||||
if (window.parent && window.parent !== window && typeof window.parent.wsOpenTab === 'function') {
|
||||
window.parent.wsOpenTab(url, name || '');
|
||||
return true;
|
||||
}
|
||||
} catch (e) {}
|
||||
return false;
|
||||
}
|
||||
function go(url, name) { if (!openInTab(url, name) && url) window.location.href = url; }
|
||||
|
||||
// 자주 가는 화면·최근 방문 메뉴 링크 → 새 탭으로 열기
|
||||
document.addEventListener('click', function (e) {
|
||||
var a = e.target.closest ? e.target.closest('a.js-tab-link') : null;
|
||||
if (!a) return;
|
||||
var url = a.getAttribute('href');
|
||||
if (!url || url.charAt(0) === '#') return;
|
||||
if (openInTab(url, a.getAttribute('data-title') || (a.textContent || '').trim())) {
|
||||
e.preventDefault(); e.stopPropagation();
|
||||
}
|
||||
}, true);
|
||||
|
||||
function highlight() {
|
||||
Array.prototype.forEach.call(list.children, function (li, i) {
|
||||
@@ -178,20 +199,20 @@ $donutCss = $donutStops !== [] ? implode(', ', $donutStops) : '#e5e7eb 0% 100%';
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
var q = input.value.trim();
|
||||
if (active >= 0 && current[active]) { go(current[active].url); return; }
|
||||
if (active >= 0 && current[active]) { go(current[active].url, current[active].name); return; }
|
||||
// 전체 이름 정확히 일치 우선
|
||||
var exact = FLAT.filter(function (m) { return norm(m.name) === norm(q); });
|
||||
if (exact.length) { go(exact[0].url); return; }
|
||||
if (current.length) { go(current[0].url); return; }
|
||||
if (exact.length) { go(exact[0].url, exact[0].name); return; }
|
||||
if (current.length) { go(current[0].url, current[0].name); return; }
|
||||
var any = matches(q);
|
||||
if (any.length) { go(any[0].url); return; }
|
||||
if (any.length) { go(any[0].url, any[0].name); return; }
|
||||
alert('일치하는 메뉴가 없습니다.');
|
||||
}
|
||||
});
|
||||
|
||||
list.addEventListener('mousedown', function (e) {
|
||||
var li = e.target.closest('li[data-url]');
|
||||
if (li) { e.preventDefault(); go(li.getAttribute('data-url')); }
|
||||
if (li) { e.preventDefault(); var i = +li.getAttribute('data-i'); go(li.getAttribute('data-url'), current[i] && current[i].name); }
|
||||
});
|
||||
|
||||
document.addEventListener('click', function (e) {
|
||||
@@ -279,7 +300,7 @@ $donutCss = $donutStops !== [] ? implode(', ', $donutStops) : '#e5e7eb 0% 100%';
|
||||
];
|
||||
foreach ($links as [$path, $label, $desc, $icon, $c]):
|
||||
?>
|
||||
<a href="<?= base_url($path) ?>" class="group flex items-center gap-3 px-3 py-2 rounded border border-gray-200 hover:border-blue-500 hover:bg-blue-50/40 transition">
|
||||
<a href="<?= base_url($path) ?>" data-title="<?= esc($label, 'attr') ?>" class="js-tab-link group flex items-center gap-3 px-3 py-2 rounded border border-gray-200 hover:border-blue-500 hover:bg-blue-50/40 transition">
|
||||
<div class="h-8 w-8 rounded-full bg-<?= $c ?>-50 text-<?= $c ?>-600 flex items-center justify-center shrink-0">
|
||||
<i class="fa-solid <?= $icon ?>"></i>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user