@crazy-web/feedback
Version:
A feedback form handler package that shows a popup based on allowed URLs.
274 lines (273 loc) • 16.1 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.submitIdea = exports.roadMapContainer = void 0;
exports.renderFeedbacks = renderFeedbacks;
const config_1 = require("../core/lib/config");
const enum_1 = require("../core/lib/enum");
const fetchRoadMaps_1 = require("../core/usecases/fetchRoadMaps");
const handleSubmit_1 = require("../core/usecases/handleSubmit");
const feedbackDetails_1 = require("./feedbackDetails");
const ideas_1 = require("./ideas");
const checkIsDarkMode_1 = require("./reuseables/checkIsDarkMode");
const featureCard_1 = require("./reuseables/featureCard");
const roadMapContainer = (data, selectedCard) => __awaiter(void 0, void 0, void 0, function* () {
const { orgData, form, config } = data;
const { primaryColor = config_1.configData === null || config_1.configData === void 0 ? void 0 : config_1.configData.primaryColor, heading = config_1.configData.heading, theme = config_1.configData === null || config_1.configData === void 0 ? void 0 : config_1.configData.theme } = config !== null && config !== void 0 ? config : {};
const isDarkMode = (0, checkIsDarkMode_1.checkIsDarkMode)({ theme });
const accountId = orgData === null || orgData === void 0 ? void 0 : orgData.organizationId;
const websiteId = orgData === null || orgData === void 0 ? void 0 : orgData.websiteId;
const container = document.createElement("div");
container.className = "prodio-feedback-hidden-scrollbar";
// container.style.cssText = "display:flex;flex-direction:column;gap:15px;overflow-y:auto;padding:1px;height:500px";
container.style.overflowY = "auto";
container.style.display = "flex";
container.style.flexDirection = "column";
container.style.gap = "15px";
container.style.padding = "1px";
container.style.height = "calc(100vh - 190px)";
const ideaForm = document.createElement("div");
ideaForm.innerHTML = (0, ideas_1.renderIdeaForm)(data);
container.appendChild(ideaForm);
const prodioTabContent = document.getElementById("prodio-tab-content");
prodioTabContent === null || prodioTabContent === void 0 ? void 0 : prodioTabContent.appendChild(container);
const fields = ["slider-title", "slider-type", "slider-description"];
fields.forEach((field) => {
const input = document.getElementById(field);
const label = document.querySelector(`label[for="${field}"]`);
if (input && label) {
input.addEventListener("focus", () => {
label.style.color = primaryColor;
input.style.outline = "none"; // Removes focus outline
input.style.border = "none"; // Removes border
});
input.addEventListener("blur", () => {
label.style.color = "black";
input.style.border = "none"; // Ensure border stays removed after blur
});
}
});
renderFeedbacks(accountId, websiteId, false, primaryColor, isDarkMode);
// to submit the ideas
(0, exports.submitIdea)({ orgData, primaryColor, isDarkMode });
// ✅to manage the submit a new idea button
(0, ideas_1.manageSubmitANewIdeaButton)();
// to manage click on the ideas feedback card
(0, feedbackDetails_1.onFeedbackCardClick)(selectedCard, data, primaryColor, isDarkMode);
});
exports.roadMapContainer = roadMapContainer;
function renderFeedbacks(accountId_1, websiteId_1) {
return __awaiter(this, arguments, void 0, function* (accountId, websiteId, resetData = false, primaryColor, isDarkMode) {
const container = document.querySelector(".prodio-feedback-hidden-scrollbar");
const feedbackContainer = document.getElementById("feedback-list");
if (!feedbackContainer)
return;
// Clear existing content if resetData is true
if (resetData) {
feedbackContainer.innerHTML = "";
}
// Show loading spinner
const spinner = document.createElement("div");
spinner.classList.add("spinner");
spinner.innerHTML = `
<div class="prodio-spinner-container">
<div class="prodio-spinner"></div>
</div>
`;
feedbackContainer.appendChild(spinner);
const { data } = yield (0, fetchRoadMaps_1.fetchRoadMaps)({ organizationId: accountId, websiteId });
feedbackContainer.innerHTML = ""; // Remove spinner after loading
feedbackContainer.style.display = "flex";
feedbackContainer.style.flexDirection = "column";
feedbackContainer.style.gap = "15px";
const borderColor = isDarkMode ? "1px solid #292B2F" : "1px solid #31333740";
const headerColor = isDarkMode ? "#D2D3E0" : "#303540";
const counterBackgroundColor = isDarkMode ? "#FFFFFFD9" : "#1F2026D9";
const counterTextColor = isDarkMode ? "#1F2026" : "#F8F9FA";
// Render accordions
data.forEach((section, index) => {
var _a, _b, _c, _d, _e, _f;
// Create accordion container
const accordion = document.createElement("div");
accordion.classList.add("accordion");
accordion.style.border = borderColor;
// accordion.style.borderTop = `2px solid ${FeedbackStatus[section?.status]?.color}`
// accordion.style.boxShadow = "0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24)"
accordion.style.borderRadius = "8px";
// Create status (accordion header)
const statusHeader = document.createElement("div");
statusHeader.classList.add("accordion-header");
// <span style="width: 8px; height: 8px; border-radius: 50%; background-color:${FeedbackStatus[section?.status]?.color}; display: inline-block;"></span>
statusHeader.innerHTML = `
<div style="display: flex; align-items: center; gap: 6px;">
<span style="font-size: 15px; color:${headerColor}; font-weight: 600;">
${(_a = enum_1.FeedbackStatus[section === null || section === void 0 ? void 0 : section.status]) === null || _a === void 0 ? void 0 : _a.label}
</span>
${((_b = section === null || section === void 0 ? void 0 : section.data) === null || _b === void 0 ? void 0 : _b.length) > 0 ? `<span
style="
background-color:${counterBackgroundColor};
color:${counterTextColor};
padding: 2px 6px;
border-radius:8px;
font-size: 12px;
font-weight: 500;
margin-left: 15px;
"
>
${(_c = section === null || section === void 0 ? void 0 : section.data) === null || _c === void 0 ? void 0 : _c.length} ${((_d = section === null || section === void 0 ? void 0 : section.data) === null || _d === void 0 ? void 0 : _d.length) === 1 ? "Item" : "Items"}
</span>` : ``}
</div>
`;
statusHeader.style.cursor = "pointer";
statusHeader.style.fontSize = "16px";
statusHeader.style.padding = "10px 20px";
statusHeader.style.display = "flex";
statusHeader.style.justifyContent = "space-between";
statusHeader.style.alignItems = "center";
statusHeader.style.zIndex = "99999999";
statusHeader.style.borderBottom = borderColor;
// Add arrow icon
const arrow = document.createElement("span");
arrow.innerHTML = renderAccordionCloseIcon({ stroke: headerColor }); // Closed state
statusHeader.appendChild(arrow);
// Create content container
const content = document.createElement("div");
content.classList.add("accordion-content");
content.style.display = "block";
// content.style.border = "1px solid #ddd";
// content.style.borderTop = "none";
content.style.marginBottom = "10px";
// Render cards
if (((_e = section === null || section === void 0 ? void 0 : section.data) === null || _e === void 0 ? void 0 : _e.length) > 0) {
(_f = section === null || section === void 0 ? void 0 : section.data) === null || _f === void 0 ? void 0 : _f.forEach((item, idx) => {
const card = document.createElement("div");
card.innerHTML = (0, featureCard_1.FeatureCards)(item, idx, "card", primaryColor, 2, isDarkMode);
card.setAttribute("data-feedback", JSON.stringify(item));
card.setAttribute("data-feedback-id", item === null || item === void 0 ? void 0 : item.id);
content.appendChild(card);
});
}
else {
content.innerHTML = `<div class="prodio-no-data">No ideas found.</div>`;
}
// Toggle accordion on click
statusHeader.addEventListener("click", () => {
const isOpen = content.style.display === "block";
statusHeader.style.borderBottom = !isOpen ? borderColor : "none"; // Toggle border
content.style.display = isOpen ? "none" : "block";
arrow.innerHTML = !isOpen ? renderAccordionCloseIcon({ stroke: headerColor }) : renderAccordionOpenIcon({ stroke: headerColor }); // Toggle arrow
});
// Prevent event bubbling when clicking the arrow
arrow.addEventListener("click", (event) => {
event.stopPropagation(); // Stop the event from reaching statusHeader
const isOpen = content.style.display === "block";
content.style.display = isOpen ? "none" : "block";
arrow.innerHTML = !isOpen ? renderAccordionCloseIcon({ stroke: headerColor }) : renderAccordionOpenIcon({ stroke: headerColor }); // Toggle arrow
});
// Append elements
accordion.appendChild(statusHeader);
accordion.appendChild(content);
feedbackContainer.appendChild(accordion);
});
});
}
const submitIdea = ({ orgData, primaryColor, isDarkMode }) => {
var _a;
const inputs = [
document.getElementById("slider-type"),
document.getElementById("slider-title"),
document.getElementById("slider-description")
];
inputs.forEach(input => {
input.addEventListener("input", () => {
input.style.border = "none";
document.getElementById("slider-error").style.display = "none";
});
});
(_a = document.getElementById("slider-submit")) === null || _a === void 0 ? void 0 : _a.addEventListener("click", () => __awaiter(void 0, void 0, void 0, function* () {
var _a, _b, _c;
const submitButton = document.getElementById("slider-submit");
const type = document.getElementById("slider-type").value;
const title = document.getElementById("slider-title").value;
const description = document.getElementById("slider-description").value;
const accountId = orgData === null || orgData === void 0 ? void 0 : orgData.organizationId;
const websiteId = orgData;
// let hasError = false;
// inputs.forEach(input => {
// if (!input.value.trim()) {
// input.style.border = "1px solid red";
// hasError = true;
// }
// });
// if (hasError) {
// document.getElementById("slider-error")!.style.display = "block";
// return;
// }
if (!title.trim() || !description.trim()) {
document.getElementById("slider-error").style.display = "block";
return;
}
submitButton.disabled = true;
submitButton.classList.add("prodio-disabled-btn");
const website = window.location.hostname;
const dataToSend = {
title: title,
description: description !== null && description !== void 0 ? description : "",
type: type, // How we will define its a type of feature, tasks, or bug, we can add more types here.
feedback_id: "",
source: {
id: website,
name: "slider", //popup
type: "Website",
},
user_id: (_a = orgData === null || orgData === void 0 ? void 0 : orgData.userData) === null || _a === void 0 ? void 0 : _a.id,
user_name: (_b = orgData === null || orgData === void 0 ? void 0 : orgData.userData) === null || _b === void 0 ? void 0 : _b.name,
user_email: (_c = orgData === null || orgData === void 0 ? void 0 : orgData.userData) === null || _c === void 0 ? void 0 : _c.email,
created_at: new Date(),
updated_at: new Date(),
last_retrieved_message: false,
account_id: orgData === null || orgData === void 0 ? void 0 : orgData.organizationId,
meta_data: null,
is_public: false, // false
website_id: orgData === null || orgData === void 0 ? void 0 : orgData.websiteId,
submission_mode: enum_1.SubmissionMode.feedback
};
const res = yield (0, handleSubmit_1.handleSubmit)(dataToSend);
if (res.error) {
document.getElementById("slider-error").textContent = res.error;
document.getElementById("slider-error").style.display = "block";
}
else {
renderFeedbacks(accountId, websiteId, true, primaryColor, isDarkMode);
document.getElementById("slider-title").value = "";
document.getElementById("slider-description").value = "";
}
submitButton.disabled = false;
submitButton.classList.remove("prodio-disabled-btn");
}));
};
exports.submitIdea = submitIdea;
const renderAccordionCloseIcon = ({ stroke }) => {
return `
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke=${stroke} stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>
`;
// return `
// <svg width="15px" height="15px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg" fill=${stroke}><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M903.232 768l56.768-50.432L512 256l-448 461.568 56.768 50.432L512 364.928z" fill=${stroke}></path></g></svg>
// `
};
const renderAccordionOpenIcon = ({ stroke }) => {
// return `
// <svg width="15px" height="15px" viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg" fill=${stroke}><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M903.232 256l56.768 50.432L512 768 64 306.432 120.768 256 512 659.072z" fill=${stroke}></path></g></svg>
// `
return `
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke=${stroke} stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-right-icon lucide-chevron-right"><path d="m9 18 6-6-6-6"/></svg>
`;
};