MediaWiki:Common.js: Perbedaan antara revisi
Tidak ada ringkasan suntingan Tanda: Suntingan perangkat seluler Suntingan peramban seluler |
Tidak ada ringkasan suntingan Tanda: Suntingan perangkat seluler Suntingan peramban seluler |
||
| Baris 154: | Baris 154: | ||
/* ========================================================== | /* ========================================================== | ||
📦 MIPPEDIA DATA - TOP PERMANENT HEADER | 📦 MIPPEDIA DATA - TOP PERMANENT HEADER | ||
Fungsi: | Fungsi: Identitas project (Hanya di Namespace Utama) | ||
========================================================== */ | ========================================================== */ | ||
(function() { | (function() { | ||
$(document).ready(function() { | $(document).ready(function() { | ||
// | // PROTEKSI NAMESPACE: Hanya muncul di artikel utama (0), bukan Talk, User, atau Project. | ||
if (mw.config.get(' | if (mw.config.get('wgNamespaceNumber') !== 0 || mw.config.get('wgAction') !== 'view') return; | ||
var headerHtml = | var headerHtml = | ||
| Baris 173: | Baris 173: | ||
'</div>'; | '</div>'; | ||
$('#mw-content-text').prepend(headerHtml); | $('#mw-content-text').prepend(headerHtml); | ||
}); | }); | ||
| Baris 180: | Baris 179: | ||
/* ========================================================== | /* ========================================================== | ||
🛡️ MIPPEDIA DATA - BOTTOM PERMANENT FOOTER | 🛡️ MIPPEDIA DATA - BOTTOM PERMANENT FOOTER | ||
Fungsi: | Fungsi: Lisensi & Atribusi (Hanya di Namespace Utama) | ||
========================================================== */ | ========================================================== */ | ||
(function() { | (function() { | ||
$(document).ready(function() { | $(document).ready(function() { | ||
// | // PROTEKSI NAMESPACE: Hanya muncul di artikel utama (0) | ||
if (mw.config.get(' | if (mw.config.get('wgNamespaceNumber') !== 0 || mw.config.get('wgAction') !== 'view') return; | ||
var footerHtml = | var footerHtml = | ||
| Baris 197: | Baris 196: | ||
'</div>'; | '</div>'; | ||
$('#mw-content-text').append(footerHtml); | $('#mw-content-text').append(footerHtml); | ||
}); | }); | ||
| Baris 203: | Baris 201: | ||
/* ========================================================== | /* ========================================================== | ||
🔗 MIPPEDIA DATA - ULTIMATE SITELINK CONNECTOR ( | 🔗 MIPPEDIA DATA - ULTIMATE SITELINK CONNECTOR (PRO V4) | ||
Status: | Status: INDUSTRIAL GRADE (Namespace Protection & API Check) | ||
========================================================== */ | ========================================================== */ | ||
(function() { | (function() { | ||
$(document).ready(function() { | $(document).ready(function() { | ||
// HANYA MUNCUL DI NAMESPACE UTAMA (0) | |||
if (mw.config.get('wgAction') !== 'view' || mw.config.get('wgNamespaceNumber') !== 0) return; | if (mw.config.get('wgAction') !== 'view' || mw.config.get('wgNamespaceNumber') !== 0) return; | ||
| Baris 218: | Baris 217: | ||
}; | }; | ||
// 1. Desain Notifikasi | // 1. Desain Notifikasi Professional & Modern | ||
function showFancyNotif(msg, type) { | function showFancyNotif(msg, type) { | ||
$('.mip-notif').remove(); | $('.mip-notif').remove(); | ||
var | var color = type === 'success' ? '#00ffa3' : '#ff4d4d'; // Neon colors | ||
var | var icon = type === 'success' ? '✓' : '✕'; | ||
var $notif = $('<div class="mip-notif" style="position:fixed; top: | |||
setTimeout(function() { $notif.css('transform', 'translateX(-50%) translateY(- | var $notif = $('<div class="mip-notif" style="position:fixed; top:40px; left:50%; transform:translateX(-50%); background:rgba(15,15,15,0.92); backdrop-filter:blur(12px); color:white; padding:14px 28px; border-radius:12px; font-size:13px; font-weight:600; z-index:10000; display:flex; align-items:center; gap:12px; box-shadow:0 15px 35px rgba(0,0,0,0.5); border:1px solid rgba(255,255,255,0.1); border-bottom:3px solid '+color+'; animation:mipSlideDown 0.5s cubic-bezier(0.19, 1, 0.22, 1);">'+ | ||
'<span style="background:'+color+'; color:#000; width:22px; height:22px; display:flex; align-items:center; justify-content:center; border-radius:50%; font-size:12px; font-weight:900;">'+icon+'</span>'+ | |||
'<span>'+msg+'</span>'+ | |||
'</div>').appendTo('body'); | |||
setTimeout(function() { | |||
$notif.css('transform', 'translateX(-50%) translateY(-20px)').css('opacity', '0').css('transition', '0.4s'); | |||
setTimeout(function(){ $notif.remove(); }, 400); | |||
}, 3800); | |||
} | } | ||
| Baris 233: | Baris 240: | ||
renderLinks(content[pageTitle] || {}); | renderLinks(content[pageTitle] || {}); | ||
}).fail(function() { | }).fail(function() { | ||
$('#mip-link-display').html('<em style="color:# | $('#mip-link-display').html('<em style="color:#ff4d4d; font-size:12px;">Pusat data tidak merespon.</em>'); | ||
}); | }); | ||
} | } | ||
| Baris 245: | Baris 252: | ||
$display.append('<a class="mip-pill" style="background:'+projects[p].color+'" href="'+projects[p].base+encodeURIComponent(links[p])+'" target="_blank">Mippedia '+projects[p].name+': '+links[p]+'</a>'); | $display.append('<a class="mip-pill" style="background:'+projects[p].color+'" href="'+projects[p].base+encodeURIComponent(links[p])+'" target="_blank">Mippedia '+projects[p].name+': '+links[p]+'</a>'); | ||
$('#input-' + p).val(links[p]); | $('#input-' + p).val(links[p]); | ||
} else { | } else { $('#input-' + p).val(''); } | ||
}); | }); | ||
if (!hasAny) $display.html('<em style="color:# | if (!hasAny) $display.html('<em style="color:#888; font-size:12px; font-style:normal;">Belum ada koneksi ekosistem.</em>'); | ||
} | } | ||
// 3. | // 3. UI Construction | ||
var editIcon = mw.config.get('wgUserGroups').includes('sysop') || !mw.config.get('wgRestrictionEdit').includes('sysop') ? '<span id="mip-edit-links" style="cursor:pointer; color:#6a5acd; font-size:18px; transition:0.3s;">✎</span>' : ''; | var editIcon = mw.config.get('wgUserGroups').includes('sysop') || !mw.config.get('wgRestrictionEdit').includes('sysop') ? '<span id="mip-edit-links" style="cursor:pointer; color:#6a5acd; font-size:18px; transition:0.3s; opacity:0.7;">✎</span>' : ''; | ||
var uiHtml = '<div id="mip-sitelink-box" style="background:#fff; border:1px solid # | var uiHtml = '<div id="mip-sitelink-box" style="background:#fff; border:1px solid #e0e0e0; border-radius:14px; padding:20px; margin-top:25px; box-shadow:0 8px 24px rgba(0,0,0,0.04);">' + | ||
'<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom: | '<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:18px;">' + | ||
'<strong style="font-size:14px; color:# | '<strong style="font-size:14px; color:#1a1a1a; letter-spacing:-0.2px;">🔗 Koneksi Ekosistem Mippedia</strong>' + editIcon + '</div>' + | ||
'<div id="mip-link-display" style="display:flex; gap:10px; flex-wrap:wrap;"><div class="mip-loader"></div></div>' + | '<div id="mip-link-display" style="display:flex; gap:10px; flex-wrap:wrap;"><div class="mip-loader"></div></div>' + | ||
'<div id="mip-link-editor" style="display:none; margin-top: | '<div id="mip-link-editor" style="display:none; margin-top:18px; border-top:1px solid #f0f0f0; padding-top:18px;">' + | ||
Object.keys(projects).map(p => '<div style="margin-bottom: | Object.keys(projects).map(p => '<div style="margin-bottom:10px; display:flex; gap:10px;"><span style="width:65px; font-size:10px; font-weight:800; background:#f5f5f5; display:flex; align-items:center; justify-content:center; border-radius:8px; color:#666;">'+projects[p].name+'</span><input type="text" id="input-'+p+'" placeholder="Ketik judul artikel..." style="flex:1; padding:9px 12px; font-size:13px; border:1.5px solid #eee; border-radius:8px; outline:none; transition:0.2s;" onfocus="this.style.borderColor=\'#6a5acd\'" onblur="this.style.borderColor=\'#eee\'"></div>').join('') + | ||
'<button id="mip-save-links" style="width:100%; margin-top: | '<button id="mip-save-links" style="width:100%; margin-top:12px; padding:12px; background:#6a5acd; color:white; border:none; border-radius:10px; font-size:13px; font-weight:700; cursor:pointer; transition:0.3s; box-shadow:0 4px 12px rgba(106,90,205,0.2);">Sinkronkan Data</button></div></div>' + | ||
'<style>@keyframes | '<style>@keyframes mipSlideDown{from{top:0; opacity:0;} to{top:40px; opacity:1;}} .mip-pill{color:white !important; padding:7px 15px; border-radius:8px; font-size:11px; font-weight:700; text-decoration:none !important; transition:0.3s; border-bottom:2px solid rgba(0,0,0,0.15);} .mip-pill:hover{transform:translateY(-2px); box-shadow:0 5px 10px rgba(0,0,0,0.12); opacity:0.9;}</style>'; | ||
$('#mip-data-footer').before(uiHtml); | $('#mip-data-footer').before(uiHtml); | ||
// 4. | // 4. Brain Function: Verification & Storage | ||
$(document).on('click', '#mip-save-links', function() { | $(document).on('click', '#mip-save-links', function() { | ||
var $btn = $(this); | var $btn = $(this); | ||
var api = new mw.Api(); | var api = new mw.Api(); | ||
var newData = {}; | |||
var isDeleting = true; | |||
var checkPromises = []; | |||
var invalidTitles = []; | |||
$btn.text('Memverifikasi Artikel...').prop('disabled', true); | |||
// Validasi Input & Cek API per Proyek | |||
Object.keys(projects).forEach(p => { | |||
if (v) { newData[p] = v; | var v = $('#input-' + p).val().trim(); | ||
if (v) { | |||
isDeleting = false; | |||
var promise = $.ajax({ | |||
url: projects[p].url, | |||
data: { action: 'query', titles: v, format: 'json', origin: '*' }, | |||
dataType: 'json' | |||
}).done(function(data) { | |||
if (data.query.pages["-1"] !== undefined) { | |||
invalidTitles.push(projects[p].name + ': "' + v + '"'); | |||
} else { | |||
newData[p] = v; | |||
} | |||
}); | |||
checkPromises.push(promise); | |||
} | |||
}); | |||
if ( | $.when.apply($, checkPromises).then(function() { | ||
if (invalidTitles.length > 0) { | |||
showFancyNotif('Judul Tidak Ditemukan: ' + invalidTitles.join(', '), 'error'); | |||
$btn.text('Sinkronkan Data').prop('disabled', false); | |||
return; | |||
} | |||
api.postWithEditToken({ | $btn.text('Menyimpan ke Server...'); | ||
api.get({ action: 'query', prop: 'revisions', titles: dataPage, rvprop: 'content', formatversion: 2 }).done(function(res) { | |||
var fullData = res.query.pages[0].revisions ? JSON.parse(res.query.pages[0].revisions[0].content) : {}; | |||
if (isDeleting) delete fullData[pageTitle]; | |||
else fullData[pageTitle] = newData; | |||
api.postWithEditToken({ | |||
action: 'edit', title: dataPage, text: JSON.stringify(fullData, null, 2), | |||
summary: 'Update Sitelink: ' + pageTitle + ' [Automated Check]', format: 'json' | |||
}).done(function() { | |||
showFancyNotif(isDeleting ? 'Koneksi Berhasil Dicabut' : 'Data Ekosistem Terkoneksi!', 'success'); | |||
setTimeout(function(){ location.reload(); }, 1200); | |||
}).fail(function(code) { | |||
showFancyNotif('Gagal: ' + code, 'error'); | |||
$btn.text('Sinkronkan Data').prop('disabled', false); | |||
}); | |||
}); | }); | ||
}); | }); | ||