This commit is contained in:
@@ -186,8 +186,10 @@
|
||||
}
|
||||
|
||||
async function requestJson(path, options) {
|
||||
if (!config.apiBaseUrl) return { local: true };
|
||||
const response = await fetch(config.apiBaseUrl.replace(/\/$/, '') + path, Object.assign({ credentials: 'include' }, options));
|
||||
const sameOriginProxy = !config.apiBaseUrl && path === config.createFeedbackPath;
|
||||
if (!config.apiBaseUrl && !sameOriginProxy) return { local: true };
|
||||
const target = config.apiBaseUrl ? config.apiBaseUrl.replace(/\/$/, '') + path : path;
|
||||
const response = await fetch(target, Object.assign({ credentials: 'include' }, options));
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.json().catch(function () { return {}; });
|
||||
throw new Error(errorBody.message || 'API 요청에 실패했습니다. (' + response.status + ')');
|
||||
@@ -200,12 +202,20 @@
|
||||
}
|
||||
|
||||
function makeUuid() {
|
||||
if (window.crypto && typeof window.crypto.randomUUID === 'function') return window.crypto.randomUUID();
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) {
|
||||
const random = Math.random() * 16 | 0;
|
||||
const value = char === 'x' ? random : (random & 3 | 8);
|
||||
return value.toString(16);
|
||||
});
|
||||
const bytes = new Uint8Array(16);
|
||||
if (window.crypto && typeof window.crypto.getRandomValues === 'function') window.crypto.getRandomValues(bytes);
|
||||
else for (let index = 0; index < bytes.length; index += 1) bytes[index] = Math.random() * 256 | 0;
|
||||
const timestamp = Date.now();
|
||||
bytes[0] = Math.floor(timestamp / 0x10000000000) & 0xff;
|
||||
bytes[1] = Math.floor(timestamp / 0x100000000) & 0xff;
|
||||
bytes[2] = Math.floor(timestamp / 0x1000000) & 0xff;
|
||||
bytes[3] = Math.floor(timestamp / 0x10000) & 0xff;
|
||||
bytes[4] = Math.floor(timestamp / 0x100) & 0xff;
|
||||
bytes[5] = timestamp & 0xff;
|
||||
bytes[6] = (bytes[6] & 0x0f) | 0x70;
|
||||
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
||||
const hex = Array.prototype.map.call(bytes, function (byte) { return ('0' + byte.toString(16)).slice(-2); }).join('');
|
||||
return hex.slice(0, 8) + '-' + hex.slice(8, 12) + '-' + hex.slice(12, 16) + '-' + hex.slice(16, 20) + '-' + hex.slice(20);
|
||||
}
|
||||
|
||||
async function sha256(file) {
|
||||
@@ -242,38 +252,12 @@
|
||||
|
||||
function buildFeedbackPayload(post, user, feedbackId, attachments) {
|
||||
const categoryCode = CATEGORY_CODES[post.category];
|
||||
const source = { namespace: config.sourceNamespace, recordId: feedbackId };
|
||||
const imageMetadata = attachments.filter(function (item) { return item.purpose === 'FEEDBACK_ATTACHMENT'; }).map(function (item) {
|
||||
return { id: item.id, original_file_name: item.originalFileName, storage_bucket: item.storageBucket, storage_key: item.storageKey, mime_type: item.mimeType, file_size: item.fileSize, checksum_sha256: item.checksumSha256 };
|
||||
});
|
||||
const data = {
|
||||
id: feedbackId,
|
||||
createdAt: post.createdAt,
|
||||
title: post.title,
|
||||
contents: post.content,
|
||||
priority: 'MEDIUM',
|
||||
Category: categoryCode,
|
||||
requester_id: user.requesterId,
|
||||
requester_tenant_id: user.requesterTenantId,
|
||||
requester_email: user.email,
|
||||
requester_name: user.name,
|
||||
requester_department: user.department,
|
||||
is_secret: post.secret ? 1 : 0,
|
||||
feedback_status: 'NEW',
|
||||
images: imageMetadata
|
||||
};
|
||||
return {
|
||||
schemaVersion: 'feedback.hmac.kr/qa.v1',
|
||||
source: source,
|
||||
feedback: { id: feedbackId, channelId: config.channelId, workspaceId: config.workspaceId, workspaceCode: config.workspaceCode, sourceNamespace: source.namespace, sourceRecordId: source.recordId, data: data },
|
||||
supportTicket: {
|
||||
workspace_id: config.workspaceId, requester_id: user.requesterId, requester_tenant_id: user.requesterTenantId, ticket_type: 'QNA', source_system: 'EGBIM', title: post.title, category_code: categoryCode, status_code: 'RECEIVED', is_secret: post.secret ? 1 : 0, priority: 'NORMAL', description: post.content, approval_status: 'NOT_REQUIRED', sync_status: 'PENDING', issue_link_status: 'NOT_REQUIRED', feedback_status: 'NEW', idempotency_key: feedbackId, requester_email: user.email, requester_name: user.name, requester_department: user.department, requester_phone_number: user.phone, extra_fields: { feedback_id: feedbackId, channel_id: config.channelId }
|
||||
},
|
||||
attachments: attachments.map(function (item) { return Object.assign({}, item, { sourceNamespace: source.namespace, sourceRecordId: source.recordId }); }),
|
||||
comments: [],
|
||||
commentAttachments: [],
|
||||
author: { userUuid: user.userUuid, ssoSubject: user.ssoSubject, requesterId: user.requesterId, tenantId: user.tenantId, tenantIds: user.tenantIds, scope: user.scope, roles: user.roles, email: user.email, name: user.name, department: user.department, phone: user.phone }
|
||||
};
|
||||
const payload = { feedbackId: feedbackId, title: post.title, contents: post.content, Category: categoryCode, is_secret: post.secret ? 1 : 0 };
|
||||
if (imageMetadata.length) payload.images = imageMetadata;
|
||||
return payload;
|
||||
}
|
||||
|
||||
function initList() {
|
||||
@@ -350,7 +334,8 @@
|
||||
const attachments = await uploadFiles(qs('#attachment').files, feedbackId, 'FEEDBACK_ATTACHMENT');
|
||||
const payload = buildFeedbackPayload(post, currentUser, feedbackId, attachments);
|
||||
const result = await postToApi(config.createFeedbackPath, payload);
|
||||
if (result.local) savePost(post);
|
||||
post.id = result.id || post.id;
|
||||
savePost(post);
|
||||
showToast(result.local ? '테스트 글로 저장했습니다. UUID가 생성되었습니다.' : '문의가 등록되었습니다.');
|
||||
window.setTimeout(function () { window.location.href = 'detail.html?id=' + encodeURIComponent(post.id); }, 500);
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user