js2ts: diplomacy
- select2 관련 문제 해결?
This commit is contained in:
+1
-4
@@ -49,10 +49,7 @@ var permissionLevel = <?=$permission?>; //
|
||||
</script>
|
||||
<?=WebUtil::printJS('../d_shared/common_path.js')?>
|
||||
<?=WebUtil::printJS('dist_js/vendors.js')?>
|
||||
<?=WebUtil::printJS('dist_js/common.js')?>
|
||||
<?=WebUtil::printJS('../e_lib/select2/select2.full.min.js')?>
|
||||
<!--<?=WebUtil::printJS('../e_lib/tui.editor/tui-editor-Editor-all.min.js')?>-->
|
||||
<?=WebUtil::printJS('js/diplomacy.js')?>
|
||||
<?=WebUtil::printJS('dist_js/diplomacy.js')?>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
+36
-1
@@ -20,7 +20,7 @@ export type GeneralListResponse = {
|
||||
result: true,
|
||||
list: [
|
||||
number,
|
||||
string, 0|1,
|
||||
string, 0 | 1,
|
||||
number, number, string,
|
||||
string, string, string,
|
||||
string, string | null,
|
||||
@@ -31,4 +31,39 @@ export type GeneralListResponse = {
|
||||
number, number
|
||||
][],
|
||||
token: Record<number, number>,
|
||||
}
|
||||
|
||||
export type NationLevel = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
||||
export const NationLevelText: Record<NationLevel, string> = {
|
||||
0: '방랑군',
|
||||
1: '호족',
|
||||
2: '군벌',
|
||||
3: '주자사',
|
||||
4: '주목',
|
||||
5: '공',
|
||||
6: '왕',
|
||||
7: '황제',
|
||||
}
|
||||
|
||||
export type CityLevel = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
||||
export const CityLevelText: Record<CityLevel, string> = {
|
||||
1: '수',
|
||||
2: '진',
|
||||
3: '관',
|
||||
4: '이',
|
||||
5: '소',
|
||||
6: '중',
|
||||
7: '대',
|
||||
8: '특'
|
||||
}
|
||||
|
||||
export type NationStaticItem = {
|
||||
nation: number,
|
||||
name: string,
|
||||
color: string,
|
||||
type: string,
|
||||
level: NationLevel,
|
||||
capital: number,
|
||||
gennum: number,
|
||||
power: number,
|
||||
}
|
||||
@@ -0,0 +1,496 @@
|
||||
import $ from 'jquery';
|
||||
import { unwrap_any } from './util/unwrap_any';
|
||||
import axios from 'axios';
|
||||
import { isBrightColor } from './common_legacy';
|
||||
import { setAxiosXMLHttpRequest } from './util/setAxiosXMLHttpRequest';
|
||||
import { isString } from 'lodash';
|
||||
import { convertFormData } from './util/convertFormData';
|
||||
import { InvalidResponse, NationStaticItem } from './defs';
|
||||
import { escapeHtml } from './legacy/escapeHtml';
|
||||
import { nl2br } from './util/nl2br';
|
||||
import { unwrap } from './util/unwrap';
|
||||
import { exportWindow } from './util/exportWindow';
|
||||
import Popper from 'popper.js';
|
||||
exportWindow(Popper, 'Popper');
|
||||
import 'bootstrap';
|
||||
import 'select2/dist/js/select2.full.js'
|
||||
import { LoadingData } from 'select2';
|
||||
|
||||
declare const permissionLevel: number;
|
||||
let myNationID: number | undefined;
|
||||
|
||||
type LetterNationTarget = {
|
||||
nationID: number,
|
||||
nationName: string,
|
||||
nationColor: string,
|
||||
}
|
||||
type LetterFullTarget = LetterNationTarget & {
|
||||
nationID: number,
|
||||
nationName: string,
|
||||
nationColor: string,
|
||||
generalName: string,
|
||||
generalIcon: string,
|
||||
}
|
||||
|
||||
type LetterState = 'proposed' | 'activated' | 'cancelled' | 'replaced';
|
||||
|
||||
type LetterItem = {
|
||||
no: number,
|
||||
|
||||
src: LetterFullTarget,
|
||||
dest: LetterNationTarget | LetterFullTarget,
|
||||
prev_no: number | null,
|
||||
state: LetterState,
|
||||
state_opt: 'try_destroy_src' | 'try_destroy_dest' | null,
|
||||
brief: string,
|
||||
detail: string,
|
||||
date: string,
|
||||
}
|
||||
|
||||
|
||||
|
||||
type LetterResponse = {
|
||||
result: true,
|
||||
nations: Record<number, NationStaticItem>,
|
||||
letters: Record<number, LetterItem>,
|
||||
myNationID: number,
|
||||
}
|
||||
|
||||
const stateText: Record<LetterState, string> = {
|
||||
'proposed': '제안됨',
|
||||
'activated': '승인됨',
|
||||
'cancelled': '거부됨',
|
||||
'replaced': '대체됨',
|
||||
};
|
||||
|
||||
const stateOptionText: Record<NonNullable<LetterItem['state_opt']>, string> = {
|
||||
'try_destroy_src': '송신측의 파기 요청',
|
||||
'try_destroy_dest': '수신측의 파기 요청',
|
||||
}
|
||||
|
||||
async function submitLetter(e: JQuery.Event): Promise<void> {
|
||||
e.preventDefault();
|
||||
|
||||
const $brief = $('#inputBrief');
|
||||
const $detail = $('#inputDetail');
|
||||
const $prevNo = $('#inputPrevNo');
|
||||
const $destNation = $('#inputDestNation');
|
||||
const brief = $.trim(unwrap_any<string>($brief.val()));
|
||||
const detail = $.trim(unwrap_any<string>($detail.val()));
|
||||
let prevNo = $prevNo.val() as number | undefined;
|
||||
const destNation = unwrap_any<number>($destNation.val());
|
||||
|
||||
if (prevNo !== undefined && prevNo < 1) {
|
||||
prevNo = undefined;
|
||||
}
|
||||
|
||||
console.log(brief);
|
||||
if (!brief) {
|
||||
return;
|
||||
}
|
||||
|
||||
$brief.val('');
|
||||
$detail.val('');
|
||||
|
||||
let result: InvalidResponse;
|
||||
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_diplomacy_send_letter.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
brief: brief,
|
||||
detail: detail,
|
||||
destNation: destNation,
|
||||
prevNo: prevNo ?? null,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
if (!result.result) {
|
||||
throw result.reason;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`외교 서신을 보내는데 실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('전송했습니다.');
|
||||
location.reload();
|
||||
}
|
||||
|
||||
async function repondLetter(letterNo: number, isAgree: boolean, reason: string | null): Promise<void> {
|
||||
|
||||
let result: InvalidResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_diplomacy_respond_letter.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
letterNo: letterNo,
|
||||
isAgree: isAgree,
|
||||
reason: reason,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
if (!result.result) {
|
||||
throw result.reason;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`응답을 실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAgree) {
|
||||
alert('승인했습니다.');
|
||||
}
|
||||
else {
|
||||
alert('거부했습니다.');
|
||||
}
|
||||
location.reload();
|
||||
}
|
||||
|
||||
async function rollbackLetter(letterNo: number) {
|
||||
let result: InvalidResponse;
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_diplomacy_rollback_letter.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
letterNo: letterNo,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
if (!result.result) {
|
||||
throw result.reason;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`회수를 실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
alert('회수 했습니다.');
|
||||
location.reload();
|
||||
}
|
||||
|
||||
async function destroyLetter(letterNo: number) {
|
||||
let result: InvalidResponse | {
|
||||
result: true,
|
||||
state: LetterState
|
||||
};
|
||||
try {
|
||||
const response = await axios({
|
||||
url: 'j_diplomacy_destroy_letter.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
letterNo: letterNo,
|
||||
})
|
||||
});
|
||||
result = response.data;
|
||||
if (!result.result) {
|
||||
throw result.reason;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
alert(`회수를 실패했습니다: ${e}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.state == 'activated') {
|
||||
alert('파기를 요청 했습니다.');
|
||||
}
|
||||
else {
|
||||
alert('파기 되었습니다.');
|
||||
}
|
||||
|
||||
location.reload();
|
||||
}
|
||||
|
||||
function drawLetter(letterObj: LetterItem) {
|
||||
|
||||
if (letterObj.state == 'cancelled') {
|
||||
//TODO: 취소되거나, 대체된 문서도 보여줄 방법을 찾아볼 것
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(letterObj);
|
||||
|
||||
const $letterFrame = $('#letterTemplate > .letterFrame');
|
||||
|
||||
const srcColorFormat = {
|
||||
'background-color': letterObj.src.nationColor,
|
||||
'color': isBrightColor(letterObj.src.nationColor) ? '#000000' : '#ffffff'
|
||||
};
|
||||
|
||||
const destColorFormat = {
|
||||
'background-color': letterObj.dest.nationColor,
|
||||
'color': isBrightColor(letterObj.dest.nationColor) ? '#000000' : '#ffffff'
|
||||
};
|
||||
|
||||
const targetNation = letterObj.src.nationID == myNationID ? letterObj.dest : letterObj.src;
|
||||
const targetColor = letterObj.src.nationID == myNationID ? destColorFormat : srcColorFormat;
|
||||
|
||||
const $letter = $letterFrame.clone();
|
||||
|
||||
if (letterObj.state == 'replaced') {
|
||||
$letter.hide();
|
||||
}
|
||||
|
||||
$letter.addClass('letterObj')
|
||||
.data('no', letterObj.no)
|
||||
.data('brief', letterObj.brief)
|
||||
.data('detail', letterObj.detail)
|
||||
.attr('id', 'letter_' + letterObj.no);
|
||||
|
||||
$letter.find('.letterHeader').css(targetColor);
|
||||
$letter.find('.letterNationName').text(targetNation.nationName);
|
||||
$letter.find('.letterDate').text(letterObj.date);
|
||||
$letter.find('.letterNo').text('#' + letterObj.no);
|
||||
|
||||
$letter.find('.letterStatus').text(stateText[letterObj.state]);
|
||||
|
||||
if (letterObj.state_opt !== null) {
|
||||
$letter.find('.letterStatusOpt').text(`(${unwrap(stateOptionText[letterObj.state_opt])})`);
|
||||
}
|
||||
if (letterObj.prev_no !== null) {
|
||||
const $showPrev = $(`<a href="#">#${letterObj.prev_no}</a>`);
|
||||
$showPrev.click(function () {
|
||||
$('#letter_' + letterObj.prev_no).toggle();
|
||||
})
|
||||
$letter.find('.letterPrevNo').empty().append($showPrev);
|
||||
}
|
||||
else {
|
||||
$letter.find('.letterPrevNo').text('신규');
|
||||
}
|
||||
$letter.find('.letterBrief').html(nl2br(escapeHtml(letterObj.brief)));
|
||||
$letter.find('.letterDetail').html(nl2br(escapeHtml(letterObj.detail)));
|
||||
|
||||
$letter.find('.letterSrc .signerImg img.generalIcon').attr('src', letterObj.src.generalIcon);
|
||||
$letter.find('.letterSrc .signerNation').text(letterObj.src.nationName).css(srcColorFormat);
|
||||
$letter.find('.letterSrc .signerName').text(letterObj.src.generalName).css(srcColorFormat);
|
||||
|
||||
if ('generalName' in letterObj.dest) {
|
||||
$letter.find('.letterDest .signerImg img.generalIcon').attr('src', letterObj.dest.generalIcon);
|
||||
$letter.find('.letterDest .signerNation').text(letterObj.dest.nationName).css(destColorFormat);
|
||||
$letter.find('.letterDest .signerName').text(letterObj.dest.generalName).css(destColorFormat);
|
||||
}
|
||||
|
||||
if (letterObj.state == 'proposed' && letterObj.src.nationID != myNationID) {
|
||||
$letter.find('.btnAgree').show().click(async function (e) {
|
||||
e.preventDefault();
|
||||
if (!confirm('승인하시겠습니까?')) {
|
||||
return;
|
||||
}
|
||||
await repondLetter(letterObj.no, true, null);
|
||||
});
|
||||
$letter.find('.btnDisagree').show().click(async function (e) {
|
||||
e.preventDefault();
|
||||
let reason = prompt('거부하시겠습니까? (이유 [최대 50자])');
|
||||
if (reason === null) {
|
||||
return;
|
||||
}
|
||||
reason = reason.substr(0, 50);
|
||||
await repondLetter(letterObj.no, false, reason);
|
||||
});
|
||||
}
|
||||
|
||||
if (letterObj.state == 'proposed' && letterObj.src.nationID == myNationID) {
|
||||
$letter.find('.btnRollback').show().click(async function (e) {
|
||||
e.preventDefault();
|
||||
if (!confirm('회수하시겠습니까?')) {
|
||||
return false;
|
||||
}
|
||||
await rollbackLetter(letterObj.no);
|
||||
});
|
||||
}
|
||||
|
||||
if (letterObj.state == 'activated') {
|
||||
const $btnDestroy = $letter.find('.btnDestroy');
|
||||
if ((letterObj.src.nationID == myNationID && letterObj.state_opt == 'try_destroy_src') ||
|
||||
(letterObj.dest.nationID == myNationID && letterObj.state_opt == 'try_destroy_dest')) {
|
||||
$btnDestroy.show().prop('disabled', true);
|
||||
}
|
||||
else {
|
||||
$btnDestroy.show().click(async function (e) {
|
||||
e.preventDefault();
|
||||
if (!confirm('본 문서를 파기하겠습니까? (상호 동의 필요)')) {
|
||||
return false;
|
||||
}
|
||||
await destroyLetter(letterObj.no);
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$letter.find('.btnRenew').click(function () {
|
||||
const $inputPrevNo = $('#inputPrevNo');
|
||||
$inputPrevNo.val(letterObj.no);
|
||||
$inputPrevNo.trigger('change');
|
||||
})
|
||||
|
||||
|
||||
$('#letters').prepend($letter);
|
||||
}
|
||||
|
||||
function initNewLetterForm(lettersObj: LetterResponse) {
|
||||
console.log(lettersObj);
|
||||
const nationList: (NationStaticItem & { id: number, text: string })[] = [];
|
||||
for (const nation of Object.values(lettersObj.nations)) {
|
||||
nationList.push({
|
||||
...nation,
|
||||
id: nation.nation,
|
||||
text: nation.name,
|
||||
});
|
||||
}
|
||||
|
||||
const $destNation = $('#inputDestNation').select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "",
|
||||
language: "ko",
|
||||
width: '300px',
|
||||
containerCss: {
|
||||
display: "inline-block !important;",
|
||||
color: 'white !important'
|
||||
},
|
||||
data: nationList,
|
||||
templateResult: colorNation,
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
|
||||
|
||||
const prevNoList: {
|
||||
id: number,
|
||||
text: string,
|
||||
nation: null | number,
|
||||
}[] = [{
|
||||
id: 0,
|
||||
text: '-새 문서-',
|
||||
nation: null,
|
||||
}];
|
||||
|
||||
for(const letterObj of Object.values(lettersObj.letters)){
|
||||
if (letterObj.state == 'replaced' || letterObj.state == 'cancelled') {
|
||||
continue;
|
||||
}
|
||||
const targetNation = letterObj.src.nationID == myNationID ? letterObj.dest : letterObj.src;
|
||||
prevNoList.push({
|
||||
id: letterObj.no,
|
||||
text: `#${letterObj.no} <${targetNation.nationName}>`,
|
||||
nation: targetNation.nationID
|
||||
});
|
||||
}
|
||||
|
||||
const $inputPrevNo = $('#inputPrevNo').select2({
|
||||
theme: 'bootstrap4',
|
||||
placeholder: "",
|
||||
language: "ko",
|
||||
width: '300px',
|
||||
containerCss: {
|
||||
display: "inline-block !important;",
|
||||
color: 'white !important'
|
||||
},
|
||||
data: prevNoList,
|
||||
containerCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
dropdownCssClass: 'simple-select2-align-center bg-secondary text-secondary',
|
||||
});
|
||||
$inputPrevNo.on('change', function () {
|
||||
const data = $inputPrevNo.select2('data')[0] as unknown as typeof prevNoList[0];
|
||||
console.log(data);
|
||||
if (data.nation == null) {
|
||||
$destNation.prop("disabled", false);
|
||||
}
|
||||
else {
|
||||
$destNation.val(data.nation).prop("disabled", true);
|
||||
const $targetLetter = $('#letter_' + data.id);
|
||||
resizeTextarea($('#inputBrief').val($targetLetter.data('brief')));
|
||||
resizeTextarea($('#inputDetail').val($targetLetter.data('detail')));
|
||||
}
|
||||
});
|
||||
|
||||
$('#btnSend').click(submitLetter);
|
||||
|
||||
$('#newLetter').show();
|
||||
}
|
||||
|
||||
function drawLetters(lettersObj: LetterResponse) {
|
||||
myNationID = lettersObj.myNationID;
|
||||
|
||||
if (permissionLevel == 4) {
|
||||
initNewLetterForm(lettersObj);
|
||||
$('.letterActionPlate').show();
|
||||
}
|
||||
|
||||
$('.letterObj').detach();//첫 버전이니까 일괄 삭제 일괄 로드
|
||||
for (const letter of Object.values(lettersObj.letters)) {
|
||||
drawLetter(letter);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadLetters(): Promise<LetterResponse> {
|
||||
const response = await axios({
|
||||
url: 'j_diplomacy_get_letter.php',
|
||||
responseType: 'json',
|
||||
method: 'post',
|
||||
data: convertFormData({
|
||||
})
|
||||
});
|
||||
const result: LetterResponse|InvalidResponse = response.data;
|
||||
if(!result.result){
|
||||
throw result.reason;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function colorNation(nationInfo: { id: number, text: string, color?: string } | LoadingData) {
|
||||
if (!('color' in nationInfo)) {
|
||||
return nationInfo.text;
|
||||
}
|
||||
if (!nationInfo.color) {
|
||||
return nationInfo.text;
|
||||
}
|
||||
|
||||
const fgColor = isBrightColor(nationInfo.color) ? '#000000' : '#ffffff';
|
||||
const $nationForm = $('<div>' + nationInfo.text + '</div>').css({
|
||||
'color': fgColor,
|
||||
'background-color': nationInfo.color
|
||||
});
|
||||
return $nationForm;
|
||||
}
|
||||
|
||||
function resizeTextarea($obj: JQuery<HTMLElement>) {
|
||||
$obj.height(1).height($obj.prop('scrollHeight') + 12);
|
||||
}
|
||||
|
||||
$(async function () {
|
||||
setAxiosXMLHttpRequest();
|
||||
$('textarea.autosize').on('keydown keyup', function () {
|
||||
resizeTextarea($(this));
|
||||
})
|
||||
|
||||
try {
|
||||
const letters = await loadLetters();
|
||||
drawLetters(letters);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e);
|
||||
if (isString(e)) {
|
||||
alert(e);
|
||||
}
|
||||
else {
|
||||
alert(`실패했습니다.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
});
|
||||
@@ -35,6 +35,7 @@ module.exports = (env, argv) => {
|
||||
extExpandCity: '@/extExpandCity.ts',
|
||||
main: '@/main.ts',
|
||||
dipcenter: '@/dipcenter.ts',
|
||||
diplomacy: '@/diplomacy.ts',
|
||||
|
||||
|
||||
//FORM 입력용, frontend 변경후 제거
|
||||
|
||||
Reference in New Issue
Block a user