mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 15:58:38 +01:00
update guests logic + fix pdf
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
import type { TApiSettings } from '@schema/ApiSettingsSchema';
|
||||
import type { SettingsTemplateEntry } from './Template.vue';
|
||||
|
||||
const { project } = useProject();
|
||||
const { project, isGuest } = useProject();
|
||||
|
||||
const entries: SettingsTemplateEntry[] = [
|
||||
{ id: 'acodes', title: 'Appsumo codes', text: 'Redeem appsumo codes' },
|
||||
@@ -39,7 +39,7 @@ async function redeemCode() {
|
||||
|
||||
|
||||
<template>
|
||||
<SettingsTemplate :entries="entries" :key="project?.name || 'NONE'">
|
||||
<SettingsTemplate v-if="!isGuest" :entries="entries" :key="project?.name || 'NONE'">
|
||||
<template #acodes>
|
||||
<div class="flex items-center gap-4">
|
||||
<LyxUiInput class="w-full px-4 py-2" placeholder="Appsumo code" v-model="currentCode"></LyxUiInput>
|
||||
@@ -58,4 +58,9 @@ async function redeemCode() {
|
||||
</div>
|
||||
</template>
|
||||
</SettingsTemplate>
|
||||
|
||||
<div v-if="isGuest" class="text-lyx-text-darker flex w-full h-full justify-center mt-20">
|
||||
Guests cannot view billing
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
import DeleteDomainData from '../dialog/DeleteDomainData.vue';
|
||||
import type { SettingsTemplateEntry } from './Template.vue';
|
||||
|
||||
|
||||
const { isGuest } = useProject();
|
||||
|
||||
const entries: SettingsTemplateEntry[] = [
|
||||
{ id: 'delete_dns', title: 'Delete domain data', text: 'Delete data of a specific domain from this project' },
|
||||
{ id: 'delete_data', title: 'Delete project data', text: 'Delete all data from this project' },
|
||||
@@ -105,7 +108,7 @@ const sessionsLabel = computed(() => {
|
||||
<div class="flex flex-col">
|
||||
|
||||
<!-- <div class="text-[.9rem] text-lyx-text-darker"> Select a domain </div> -->
|
||||
<USelectMenu placeholder="Select a domain" :uiMenu="{
|
||||
<USelectMenu v-if="!isGuest" placeholder="Select a domain" :uiMenu="{
|
||||
select: 'bg-lyx-lightmode-widget-light !ring-lyx-lightmode-widget dark:!bg-lyx-widget-light !shadow-none focus:!ring-lyx-widget-lighter dark:!ring-lyx-widget-lighter',
|
||||
base: '!bg-lyx-lightmode-widget dark:!bg-lyx-widget',
|
||||
option: {
|
||||
@@ -114,6 +117,8 @@ const sessionsLabel = computed(() => {
|
||||
}
|
||||
}" :options="domains.data.value ?? []" v-model="selectedDomain"></USelectMenu>
|
||||
|
||||
<div v-if="isGuest" class="text-lyx-text-darker"> Guests cannot delete data</div>
|
||||
|
||||
<div v-if="selectedDomain" class="flex flex-col gap-2 mt-4">
|
||||
<div class="text-[.9rem] text-lyx-text-dark"> Select data to delete </div>
|
||||
|
||||
@@ -141,7 +146,7 @@ const sessionsLabel = computed(() => {
|
||||
</template>
|
||||
<template #delete_data>
|
||||
|
||||
<div
|
||||
<div v-if="!isGuest"
|
||||
class="outline rounded-lg w-full px-8 py-4 flex flex-col gap-4 outline-[1px] outline-[#541c15] bg-lyx-lightmode-widget-light dark:bg-[#1e1412]">
|
||||
<div class="poppins font-semibold"> This operation will reset this project to it's initial state (0
|
||||
visits 0 events 0 sessions) </div>
|
||||
@@ -151,6 +156,7 @@ const sessionsLabel = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="isGuest" class="text-lyx-text-darker"> Guests cannot delete data</div>
|
||||
</template>
|
||||
</SettingsTemplate>
|
||||
</template>
|
||||
|
||||
@@ -156,21 +156,29 @@ function copyProjectId() {
|
||||
<template>
|
||||
<SettingsTemplate :entries="entries" :key="project?.name || 'NONE'">
|
||||
<template #pname>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-4">
|
||||
<LyxUiInput class="w-full px-4 py-2" :disabled="isGuest" v-model="projectNameInputVal"></LyxUiInput>
|
||||
<LyxUiButton v-if="!isGuest" @click="changeProjectName()" :disabled="!canChange" type="primary"> Change
|
||||
<LyxUiButton v-if="!isGuest" @click="changeProjectName()" :disabled="!canChange" type="primary">
|
||||
Change
|
||||
</LyxUiButton>
|
||||
</div>
|
||||
<div v-if="isGuest" class="text-lyx-text-darker"> *Guests cannot change project name </div>
|
||||
</div>
|
||||
</template>
|
||||
<template #api>
|
||||
<div class="flex items-center gap-4" v-if="apiKeys && apiKeys.length < 5">
|
||||
<LyxUiInput class="grow px-4 py-2" :disabled="isGuest" placeholder="ApiKeyName" v-model="newApiKeyName">
|
||||
<div class="flex flex-col gap-2" v-if="apiKeys && apiKeys.length < 5">
|
||||
<div class="flex items-center gap-4">
|
||||
<LyxUiInput class="grow px-4 py-2" :disabled="isGuest" placeholder="ApiKeyName"
|
||||
v-model="newApiKeyName">
|
||||
</LyxUiInput>
|
||||
<LyxUiButton v-if="!isGuest" @click="createApiKey()" :disabled="newApiKeyName.length < 3"
|
||||
type="primary">
|
||||
<i class="far fa-plus"></i>
|
||||
</LyxUiButton>
|
||||
</div>
|
||||
<div v-if="isGuest" class="text-lyx-text-darker"> *Guests cannot manage api keys </div>
|
||||
</div>
|
||||
<LyxUiCard v-if="apiKeys && apiKeys.length > 0" class="w-full flex flex-col gap-4 items-center mt-4">
|
||||
<div v-for="apiKey of apiKeys" class="flex flex-col w-full">
|
||||
|
||||
@@ -212,6 +220,7 @@ function copyProjectId() {
|
||||
Delete project
|
||||
</LyxUiButton>
|
||||
</div>
|
||||
<div v-if="isGuest"> *Guests cannot delete project </div>
|
||||
</template>
|
||||
</SettingsTemplate>
|
||||
</template>
|
||||
|
||||
@@ -123,7 +123,7 @@ const { showDrawer } = useDrawer();
|
||||
<i class="fas fa-spinner text-[2rem] text-accent animate-[spin_1s_linear_infinite] duration-500"></i>
|
||||
</div>
|
||||
|
||||
<SettingsTemplate v-if="!invoicesPending && !planPending" :entries="entries">
|
||||
<SettingsTemplate v-if="!invoicesPending && !planPending && !isGuest" :entries="entries">
|
||||
<template #info>
|
||||
<div v-if="!isGuest">
|
||||
<div class="flex flex-col gap-4">
|
||||
@@ -267,6 +267,10 @@ const { showDrawer } = useDrawer();
|
||||
</CardTitled>
|
||||
</template>
|
||||
</SettingsTemplate>
|
||||
|
||||
<div v-if="isGuest" class="text-lyx-text-darker flex w-full h-full justify-center mt-20">
|
||||
Guests cannot view billing
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -98,6 +98,7 @@ const entries: SettingsTemplateEntry[] = [
|
||||
User should have been registered to Litlyx
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="isGuest" class="text-lyx-text-darker"> Guests cannot add members</div>
|
||||
</template>
|
||||
<template #members>
|
||||
|
||||
|
||||
@@ -398,24 +398,29 @@ async function clearAllChats() {
|
||||
<div :class="{ '!text-green-500': debugModeAi }" class="cursor-pointer text-red-500 w-fit"
|
||||
v-if="userRoles.isAdmin.value" @click="debugModeAi = !debugModeAi"> Debug mode </div>
|
||||
|
||||
<div class="flex justify-between items-center pt-3">
|
||||
<div class="flex pt-3 px-4">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="bg-accent w-5 h-5 rounded-full animate-pulse">
|
||||
</div>
|
||||
<div class="manrope font-semibold text-lyx-lightmode-text dark:text-text-dirty"> {{
|
||||
chatsRemaining }} messages left
|
||||
<!-- <div class="bg-accent w-4 h-4 rounded-full animate-pulse">
|
||||
</div> -->
|
||||
<div class="manrope font-semibold text-lyx-lightmode-text dark:text-text-dirty">
|
||||
{{ chatsRemaining }} messages left
|
||||
</div>
|
||||
</div>
|
||||
<LyxUiButton v-if="!selfhosted" type="primary" class="text-[.9rem] text-center " @click="showDrawer('PRICING')">
|
||||
<div class="grow"></div>
|
||||
<LyxUiButton v-if="!selfhosted" type="primary" class="text-[.9rem] text-center "
|
||||
@click="showDrawer('PRICING')">
|
||||
Upgrade
|
||||
</LyxUiButton>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="dark:bg-lyx-widget-light bg-lyx-lightmode-widget-light h-[1px]"></div>
|
||||
|
||||
<div class="flex items-center gap-4 px-4 mt-4">
|
||||
<div class="poppins font-semibold text-[1.1rem]"> History </div>
|
||||
<div class="grow"></div>
|
||||
<LyxUiButton v-if="chatsList && chatsList.length > 0" @click="clearAllChats()" type="secondary"
|
||||
class="text-center text-[.8rem]">
|
||||
Clear all
|
||||
Clear all chats
|
||||
</LyxUiButton>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ const canDownload = computed(() => {
|
||||
const metricsInfo = ref<number>(0);
|
||||
|
||||
const columns = [
|
||||
{ key: 'website', label: 'Website', sortable: true },
|
||||
{ key: 'website', label: 'Domain', sortable: true },
|
||||
{ key: 'page', label: 'Page', sortable: true },
|
||||
{ key: 'referrer', label: 'Referrer', sortable: true },
|
||||
{ key: 'browser', label: 'Browser', sortable: true },
|
||||
|
||||
@@ -71,7 +71,7 @@ async function createProject() {
|
||||
<div class="flex flex-col items-center justify-center pt-[12rem] gap-12 relative z-[10]">
|
||||
|
||||
<div class="text-[3rem] font-semibold text-center text-lyx-lightmode-text dark:text-lyx-text">
|
||||
Create your {{ isFirstProject ? 'first' : '' }} project
|
||||
Create {{ isFirstProject ? '' : 'a new' }} {{ isFirstProject ? 'your first' : '' }} project
|
||||
</div>
|
||||
|
||||
<div v-if="isFirstProject" class="text-[1.5rem]">
|
||||
|
||||
@@ -16,7 +16,7 @@ const items = [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="lg:px-10 lg:py-8 h-dvh overflow-y-auto overflow-x-hidden hide-scrollbars">
|
||||
<div class="lg:px-10 lg:py-8 h-dvh overflow-y-auto overflow-x-hidden hide-scrollbars !pb-[10rem]">
|
||||
|
||||
<div class="poppins font-semibold text-[1.3rem] lg:px-0 px-4 lg:py-0 py-4"> Settings </div>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -3,7 +3,7 @@ import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestDataOld(event, { requireSchema: false, allowLitlyx: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project } = data;
|
||||
|
||||
@@ -12,7 +12,7 @@ export type InvoiceData = {
|
||||
}
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
const data = await getRequestDataOld(event, { requireSchema: false, allowLitlyx: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project, pid } = data;
|
||||
|
||||
@@ -22,7 +22,7 @@ function getPlanToActivate(current_plan_id: number) {
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestDataOld(event, { requireSchema: false, allowGuests: false, allowLitlyx: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project, pid, user } = data;
|
||||
|
||||
@@ -4,7 +4,7 @@ import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestDataOld(event, { requireSchema: false, allowLitlyx: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project } = data;
|
||||
|
||||
@@ -33,17 +33,19 @@ function formatNumberK(value: string | number, decimals: number = 1) {
|
||||
|
||||
const LINE_SPACING = 0.5;
|
||||
|
||||
const resourcePath = process.env.MODE === 'TEST' ? './public/pdf/' : '../public/pdf/';
|
||||
|
||||
function createPdf(data: PDFGenerationData) {
|
||||
|
||||
const pdf = new pdfkit({ size: 'A4', margins: { top: 50, bottom: 50, left: 50, right: 50 }, });
|
||||
pdf.fillColor('#ffffff').rect(0, 0, pdf.page.width, pdf.page.height).fill('#000000');
|
||||
|
||||
pdf.font('./server/pdf/pdf_fonts/Poppins-Bold.ttf').fontSize(16).fillColor('#ffffff');
|
||||
pdf.font(resourcePath + 'pdf_fonts/Poppins-Bold.ttf').fontSize(16).fillColor('#ffffff');
|
||||
|
||||
pdf.text(`Project name: ${data.projectName}`, { align: 'left' }).moveDown(LINE_SPACING);
|
||||
pdf.text(`Timeframe name: ${data.snapshotName}`, { align: 'left' }).moveDown(LINE_SPACING);
|
||||
|
||||
pdf.font('./server/pdf/pdf_fonts/Poppins-Regular.ttf').fontSize(12).fillColor('#ffffff')
|
||||
pdf.font(resourcePath + 'pdf_fonts/Poppins-Regular.ttf').fontSize(12).fillColor('#ffffff')
|
||||
|
||||
pdf.text(`Total visits: ${data.totalVisits}`, { align: 'left' }).moveDown(LINE_SPACING);
|
||||
pdf.text(`Average visits per day: ${data.avgVisitsDay}`, { align: 'left' }).moveDown(LINE_SPACING);
|
||||
@@ -64,16 +66,16 @@ function createPdf(data: PDFGenerationData) {
|
||||
pdf.text('Average growth:', { align: 'left' }).moveDown(LINE_SPACING);
|
||||
pdf.text(`${data.avgGrowthText}`, { align: 'left' }).moveDown(LINE_SPACING);
|
||||
|
||||
pdf.font('./server/pdf/pdf_fonts/Poppins-Italic.ttf')
|
||||
pdf.font(resourcePath + 'pdf_fonts/Poppins-Italic.ttf')
|
||||
.text('This gives you an idea of the average growth your website is experiencing over time.', { align: 'left' })
|
||||
.moveDown(LINE_SPACING);
|
||||
|
||||
pdf.font('./server/pdf/pdf_fonts/Poppins-Regular.ttf')
|
||||
pdf.font(resourcePath + 'pdf_fonts/Poppins-Regular.ttf')
|
||||
.fontSize(10)
|
||||
.fillColor('#ffffff')
|
||||
.text('Created with Litlyx.com', 50, 760, { align: 'center' });
|
||||
|
||||
pdf.image('./server/pdf/pdf_images/logo.png', 460, 700, { width: 100 });
|
||||
pdf.image(resourcePath + 'pdf_images/logo.png', 460, 700, { width: 100 });
|
||||
|
||||
pdf.end();
|
||||
return pdf;
|
||||
|
||||
@@ -3,7 +3,7 @@ import StripeService from '~/server/services/StripeService';
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestDataOld(event, { requireSchema: false, allowLitlyx: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project, project_id } = data;
|
||||
|
||||
@@ -3,11 +3,10 @@ import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { SessionModel } from "@schema/metrics/SessionSchema";
|
||||
import { VisitModel } from "@schema/metrics/VisitSchema";
|
||||
import { Types } from "mongoose";
|
||||
import { getRequestDataOld } from "~/server/utils/getRequestData";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestDataOld(event, { requireSchema: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project_id } = data;
|
||||
|
||||
@@ -3,11 +3,10 @@ import { EventModel } from "@schema/metrics/EventSchema";
|
||||
import { SessionModel } from "@schema/metrics/SessionSchema";
|
||||
import { VisitModel } from "@schema/metrics/VisitSchema";
|
||||
import { Types } from "mongoose";
|
||||
import { getRequestDataOld } from "~/server/utils/getRequestData";
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestDataOld(event, { requireSchema: false });
|
||||
const data = await getRequestData(event, []);
|
||||
if (!data) return;
|
||||
|
||||
const { project_id } = data;
|
||||
|
||||
Reference in New Issue
Block a user