Replace distribution JSON editor with form UI
This commit is contained in:
@@ -5,7 +5,10 @@ const state = {
|
||||
},
|
||||
meta: null,
|
||||
selectedProfileId: null,
|
||||
dirty: false
|
||||
dirty: false,
|
||||
distributionEditor: {
|
||||
document: null
|
||||
}
|
||||
}
|
||||
|
||||
const profileList = document.getElementById('profileList')
|
||||
@@ -26,7 +29,9 @@ const createDistributionButton = document.getElementById('createDistributionButt
|
||||
const distributionEditorModal = document.getElementById('distributionEditorModal')
|
||||
const distributionEditorHint = document.getElementById('distributionEditorHint')
|
||||
const distributionEditorStatus = document.getElementById('distributionEditorStatus')
|
||||
const distributionEditorTextarea = document.getElementById('distributionEditorTextarea')
|
||||
const distributionEditorForm = document.getElementById('distributionEditorForm')
|
||||
const distributionModuleCount = document.getElementById('distributionModuleCount')
|
||||
const distributionAdditionalServerCount = document.getElementById('distributionAdditionalServerCount')
|
||||
const closeDistributionEditorButton = document.getElementById('closeDistributionEditorButton')
|
||||
const loadDistributionTemplateButton = document.getElementById('loadDistributionTemplateButton')
|
||||
const saveDistributionFileButton = document.getElementById('saveDistributionFileButton')
|
||||
@@ -49,6 +54,18 @@ const fieldElements = {
|
||||
serverWhitelistEnabled: document.getElementById('field-serverWhitelistEnabled')
|
||||
}
|
||||
|
||||
const distributionFieldElements = {
|
||||
version: document.getElementById('distribution-field-version'),
|
||||
rss: document.getElementById('distribution-field-rss'),
|
||||
serverId: document.getElementById('distribution-field-serverId'),
|
||||
serverName: document.getElementById('distribution-field-serverName'),
|
||||
serverDescription: document.getElementById('distribution-field-serverDescription'),
|
||||
serverVersion: document.getElementById('distribution-field-serverVersion'),
|
||||
minecraftVersion: document.getElementById('distribution-field-minecraftVersion'),
|
||||
mainServer: document.getElementById('distribution-field-mainServer'),
|
||||
autoconnect: document.getElementById('distribution-field-autoconnect')
|
||||
}
|
||||
|
||||
function slugify(value){
|
||||
return String(value ?? '')
|
||||
.trim()
|
||||
@@ -61,6 +78,94 @@ function isRemoteUrl(value){
|
||||
return /^https?:\/\//i.test(String(value ?? '').trim())
|
||||
}
|
||||
|
||||
function deepClone(value){
|
||||
return value == null ? value : JSON.parse(JSON.stringify(value))
|
||||
}
|
||||
|
||||
function getDistributionTemplateProfileDefaults(profile){
|
||||
const safeId = slugify(profile?.id || profile?.name || 'example-profile') || 'example-profile'
|
||||
return {
|
||||
version: '1.0.0',
|
||||
rss: '',
|
||||
servers: [
|
||||
{
|
||||
id: safeId,
|
||||
name: profile?.name || '새 프로필',
|
||||
description: profile?.description || '관리자 사이트에서 만든 distribution 템플릿입니다.',
|
||||
version: '1.0.0',
|
||||
minecraftVersion: '1.20.1',
|
||||
mainServer: true,
|
||||
autoconnect: false,
|
||||
modules: []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeDistributionDocument(rawDocument, profile){
|
||||
const baseDocument = deepClone(rawDocument) ?? {}
|
||||
const defaultDocument = getDistributionTemplateProfileDefaults(profile)
|
||||
const servers = Array.isArray(baseDocument.servers) && baseDocument.servers.length > 0
|
||||
? baseDocument.servers
|
||||
: defaultDocument.servers
|
||||
const primaryServer = {
|
||||
...defaultDocument.servers[0],
|
||||
...(servers[0] ?? {})
|
||||
}
|
||||
|
||||
baseDocument.version = typeof baseDocument.version === 'string' && baseDocument.version.trim().length > 0
|
||||
? baseDocument.version.trim()
|
||||
: defaultDocument.version
|
||||
baseDocument.rss = typeof baseDocument.rss === 'string' ? baseDocument.rss.trim() : ''
|
||||
baseDocument.servers = [primaryServer, ...servers.slice(1)]
|
||||
|
||||
return baseDocument
|
||||
}
|
||||
|
||||
function populateDistributionEditorForm(documentData, profile){
|
||||
const normalized = normalizeDistributionDocument(documentData, profile)
|
||||
const primaryServer = normalized.servers[0]
|
||||
|
||||
state.distributionEditor.document = normalized
|
||||
distributionFieldElements.version.value = normalized.version ?? ''
|
||||
distributionFieldElements.rss.value = normalized.rss ?? ''
|
||||
distributionFieldElements.serverId.value = primaryServer.id ?? ''
|
||||
distributionFieldElements.serverName.value = primaryServer.name ?? ''
|
||||
distributionFieldElements.serverDescription.value = primaryServer.description ?? ''
|
||||
distributionFieldElements.serverVersion.value = primaryServer.version ?? ''
|
||||
distributionFieldElements.minecraftVersion.value = primaryServer.minecraftVersion ?? ''
|
||||
distributionFieldElements.mainServer.checked = primaryServer.mainServer !== false
|
||||
distributionFieldElements.autoconnect.checked = primaryServer.autoconnect === true
|
||||
|
||||
const moduleCount = Array.isArray(primaryServer.modules) ? primaryServer.modules.length : 0
|
||||
const additionalServerCount = Math.max(0, normalized.servers.length - 1)
|
||||
distributionModuleCount.textContent = `${moduleCount}개`
|
||||
distributionAdditionalServerCount.textContent = `${additionalServerCount}개`
|
||||
}
|
||||
|
||||
function buildDistributionDocumentFromForm(profile){
|
||||
const baseDocument = normalizeDistributionDocument(state.distributionEditor.document, profile)
|
||||
const primaryServer = {
|
||||
...baseDocument.servers[0]
|
||||
}
|
||||
|
||||
baseDocument.version = distributionFieldElements.version.value.trim() || '1.0.0'
|
||||
baseDocument.rss = distributionFieldElements.rss.value.trim()
|
||||
|
||||
primaryServer.id = distributionFieldElements.serverId.value.trim() || slugify(profile?.id || profile?.name || 'example-profile') || 'example-profile'
|
||||
primaryServer.name = distributionFieldElements.serverName.value.trim() || profile?.name || '새 프로필'
|
||||
primaryServer.description = distributionFieldElements.serverDescription.value.trim()
|
||||
primaryServer.version = distributionFieldElements.serverVersion.value.trim() || '1.0.0'
|
||||
primaryServer.minecraftVersion = distributionFieldElements.minecraftVersion.value.trim() || '1.20.1'
|
||||
primaryServer.mainServer = distributionFieldElements.mainServer.checked
|
||||
primaryServer.autoconnect = distributionFieldElements.autoconnect.checked
|
||||
primaryServer.modules = Array.isArray(primaryServer.modules) ? primaryServer.modules : []
|
||||
|
||||
baseDocument.servers = [primaryServer, ...baseDocument.servers.slice(1)]
|
||||
state.distributionEditor.document = baseDocument
|
||||
return baseDocument
|
||||
}
|
||||
|
||||
function createProfile(){
|
||||
const timestamp = Date.now()
|
||||
return {
|
||||
@@ -415,7 +520,7 @@ async function loadDistributionTemplate(){
|
||||
throw new Error(result.message || 'distribution 샘플을 불러오지 못했습니다.')
|
||||
}
|
||||
|
||||
distributionEditorTextarea.value = result.content
|
||||
return JSON.parse(result.content)
|
||||
}
|
||||
|
||||
async function loadDistributionContent(requestedPath){
|
||||
@@ -425,7 +530,7 @@ async function loadDistributionContent(requestedPath){
|
||||
throw new Error(result.message || 'distribution 파일을 불러오지 못했습니다.')
|
||||
}
|
||||
|
||||
distributionEditorTextarea.value = result.content
|
||||
return JSON.parse(result.content)
|
||||
}
|
||||
|
||||
async function openDistributionEditor(mode){
|
||||
@@ -436,7 +541,8 @@ async function openDistributionEditor(mode){
|
||||
}
|
||||
|
||||
openDistributionEditorModal()
|
||||
distributionEditorTextarea.value = ''
|
||||
distributionEditorForm.reset()
|
||||
state.distributionEditor.document = null
|
||||
updateDistributionEditorHint(profile)
|
||||
showDistributionEditorStatus('distribution 내용을 준비하는 중...', 'info')
|
||||
|
||||
@@ -444,7 +550,8 @@ async function openDistributionEditor(mode){
|
||||
const currentPath = String(profile.distributionUrl ?? '').trim()
|
||||
|
||||
if(mode === 'create' || currentPath.length === 0){
|
||||
await loadDistributionTemplate()
|
||||
const templateDocument = await loadDistributionTemplate()
|
||||
populateDistributionEditorForm(templateDocument, profile)
|
||||
updateDistributionEditorHint(profile, '')
|
||||
showStatus('distribution 템플릿을 불러왔습니다.', 'success')
|
||||
showDistributionEditorStatus('샘플을 불러왔습니다. 바로 수정한 뒤 저장하면 됩니다.', 'success')
|
||||
@@ -452,7 +559,8 @@ async function openDistributionEditor(mode){
|
||||
}
|
||||
|
||||
if(isRemoteUrl(currentPath)){
|
||||
await loadDistributionContent(currentPath)
|
||||
const remoteDocument = await loadDistributionContent(currentPath)
|
||||
populateDistributionEditorForm(remoteDocument, profile)
|
||||
updateDistributionEditorHint(profile, currentPath)
|
||||
showStatus('원격 distribution 내용을 불러왔습니다.', 'success')
|
||||
showDistributionEditorStatus('원격 distribution 내용을 불러왔습니다. 저장하면 로컬 파일로 복사됩니다.', 'success')
|
||||
@@ -460,7 +568,8 @@ async function openDistributionEditor(mode){
|
||||
}
|
||||
|
||||
showStatus('distribution 파일을 불러오는 중...', 'info')
|
||||
await loadDistributionContent(currentPath)
|
||||
const localDocument = await loadDistributionContent(currentPath)
|
||||
populateDistributionEditorForm(localDocument, profile)
|
||||
updateDistributionEditorHint(profile, currentPath)
|
||||
showStatus('distribution 파일을 불러왔습니다.', 'success')
|
||||
showDistributionEditorStatus('현재 연결된 distribution 파일을 불러왔습니다.', 'success')
|
||||
@@ -479,6 +588,7 @@ async function saveDistributionFile(){
|
||||
}
|
||||
|
||||
try {
|
||||
const distributionDocument = buildDistributionDocumentFromForm(profile)
|
||||
saveDistributionFileButton.disabled = true
|
||||
showStatus('distribution 파일 저장 중...', 'info')
|
||||
showDistributionEditorStatus('distribution 파일 저장 중...', 'info')
|
||||
@@ -490,7 +600,7 @@ async function saveDistributionFile(){
|
||||
},
|
||||
body: JSON.stringify({
|
||||
profileId: profile.id,
|
||||
content: distributionEditorTextarea.value
|
||||
content: JSON.stringify(distributionDocument, null, 2)
|
||||
})
|
||||
})
|
||||
const result = await response.json()
|
||||
@@ -515,6 +625,10 @@ async function saveDistributionFile(){
|
||||
}
|
||||
|
||||
function bindDistributionEditor(){
|
||||
distributionEditorForm.addEventListener('submit', (event) => {
|
||||
event.preventDefault()
|
||||
})
|
||||
|
||||
distributionEditorModal.addEventListener('click', (event) => {
|
||||
if(event.target === distributionEditorModal){
|
||||
closeDistributionEditorModal()
|
||||
@@ -538,7 +652,8 @@ window.__launcherAdminCloseDistributionEditor = () => {
|
||||
|
||||
window.__launcherAdminLoadDistributionTemplate = async () => {
|
||||
try {
|
||||
await loadDistributionTemplate()
|
||||
const templateDocument = await loadDistributionTemplate()
|
||||
populateDistributionEditorForm(templateDocument, getSelectedProfile())
|
||||
updateDistributionEditorHint(getSelectedProfile(), '')
|
||||
showStatus('distribution 템플릿을 다시 불러왔습니다.', 'success')
|
||||
showDistributionEditorStatus('샘플을 다시 불러왔습니다.', 'success')
|
||||
|
||||
Reference in New Issue
Block a user