This commit is contained in:
Rizky 2024-03-10 07:19:33 +07:00
parent 43c397c743
commit 199490b6a9
4 changed files with 22 additions and 416 deletions

View File

@ -7,19 +7,6 @@ datasource db {
url = env("DATABASE_URL") url = env("DATABASE_URL")
} }
model billing_account {
id String @id(map: "billing_account_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
id_organization String @db.Uuid
user_created String @db.Uuid
payment_info Json?
payment_method String
is_default Boolean
created_at DateTime @default(now()) @db.Timestamp(6)
updated_at DateTime @default(now()) @db.Timestamp(6)
org org @relation(fields: [id_organization], references: [id], onDelete: NoAction, onUpdate: NoAction)
user user @relation(fields: [user_created], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model component { model component {
id String @id(map: "component_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id(map: "component_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String name String
@ -36,7 +23,6 @@ model component_group {
id String @id(map: "site_comp_group_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id(map: "site_comp_group_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String name String
shared Boolean @default(false) shared Boolean @default(false)
code_assign code_assign[]
component component[] component component[]
component_site component_site[] component_site component_site[]
} }
@ -51,58 +37,6 @@ model component_site {
@@id([id_component_group, id_site], map: "component_site_id_component_group_id_site") @@id([id_component_group, id_site], map: "component_site_id_component_group_id_site")
} }
model discount {
id String @id(map: "discount_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String
code String @unique(map: "discount_code")
date_start DateTime @db.Timestamp(6)
date_end DateTime @db.Timestamp(6)
price Decimal? @db.Decimal(18, 3)
percent Float? @db.Real
max_precent Float? @db.Real
description String?
invoice_item invoice_item[]
}
model feature {
id String @id(map: "feature_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
feature Json?
price Decimal @db.Decimal(18, 3)
created_at DateTime? @default(now()) @db.Timestamp(6)
updated_at DateTime? @default(now()) @db.Timestamp(6)
name String
trial_duration Int?
subscribe_duration Int?
invoice_item invoice_item[]
}
model invoice {
id String @id(map: "invoice_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
code String
user_id String @db.Uuid
status String
total Decimal @default(0) @db.Decimal(18, 3)
due_date DateTime? @default(now()) @db.Timestamp(6)
created_at DateTime? @default(now()) @db.Timestamp(6)
updated_at DateTime? @default(now()) @db.Timestamp(6)
user user @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
invoice_item invoice_item[]
payment payment[]
}
model invoice_item {
id String @id(map: "invoice_item_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
invoice_id String @db.Uuid
feature_id String @db.Uuid
discount_id String? @db.Uuid
price Decimal @default(0) @db.Decimal(18, 3)
discount_val Decimal @default(0) @db.Decimal(18, 3)
created_at DateTime? @default(now()) @db.Timestamp(6)
discount discount? @relation(fields: [discount_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
feature feature @relation(fields: [feature_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
invoice invoice @relation(fields: [invoice_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model npm_page { model npm_page {
id BigInt @id @default(autoincrement()) id BigInt @id @default(autoincrement())
id_page String @db.Uuid id_page String @db.Uuid
@ -130,7 +64,6 @@ model org {
created_at DateTime? @default(now()) @db.Timestamp(6) created_at DateTime? @default(now()) @db.Timestamp(6)
updated_at DateTime? @db.Timestamp(6) updated_at DateTime? @db.Timestamp(6)
created_by String? @db.Uuid created_by String? @db.Uuid
billing_account billing_account[]
user user? @relation(fields: [created_by], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "organization_user_created_fkey") user user? @relation(fields: [created_by], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "organization_user_created_fkey")
org_user org_user[] org_user org_user[]
site site[] site site[]
@ -159,7 +92,6 @@ model page {
is_deleted Boolean @default(false) is_deleted Boolean @default(false)
id_layout String? @db.Uuid id_layout String? @db.Uuid
is_default_layout Boolean @default(false) is_default_layout Boolean @default(false)
code_assign code_assign[]
page_folder page_folder? @relation(fields: [id_folder], references: [id], onDelete: NoAction, onUpdate: NoAction) page_folder page_folder? @relation(fields: [id_folder], references: [id], onDelete: NoAction, onUpdate: NoAction)
page page? @relation("pageTopage", fields: [id_layout], references: [id], onDelete: NoAction, onUpdate: NoAction) page page? @relation("pageTopage", fields: [id_layout], references: [id], onDelete: NoAction, onUpdate: NoAction)
other_page page[] @relation("pageTopage") other_page page[] @relation("pageTopage")
@ -177,39 +109,6 @@ model page_folder {
site site @relation(fields: [id_site], references: [id], onDelete: NoAction, onUpdate: NoAction) site site @relation(fields: [id_site], references: [id], onDelete: NoAction, onUpdate: NoAction)
} }
model payment {
id String @id(map: "payment_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
nominal Decimal @default(0) @db.Decimal(18, 3)
id_invoice String @db.Uuid
type String? @db.VarChar(10)
payment_method String @default("CC") @db.VarChar(30)
payment_method_detail Json?
status String
payment_date DateTime? @db.Timestamp(6)
expired_date DateTime @db.Timestamp(6)
description String
created_at DateTime? @default(now()) @db.Timestamp(6)
updated_at DateTime? @default(now()) @db.Timestamp(6)
invoice invoice @relation(fields: [id_invoice], references: [id], onDelete: NoAction, onUpdate: NoAction)
payment_history payment_history[]
}
model payment_history {
id String @id(map: "payment_history_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
payment_id String @db.Uuid
status String
created_at DateTime? @default(now()) @db.Timestamp(6)
payment payment @relation(fields: [payment_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model plugin {
id String @id(map: "plugin_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String
desc String
init_script String? @default("")
site_plugin site_plugin[]
}
model site { model site {
id String @id(map: "site_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id(map: "site_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String name String
@ -227,27 +126,15 @@ model site {
responsive String @default("all") responsive String @default("all")
npm_cache String @default(" ") @db.VarChar npm_cache String @default(" ") @db.VarChar
code_mode String @default("old") @db.VarChar(5) code_mode String @default("old") @db.VarChar(5)
code code[]
component_site component_site[] component_site component_site[]
npm_site npm_site[] npm_site npm_site[]
page page[] page page[]
page_folder page_folder[] page_folder page_folder[]
org org? @relation(fields: [id_org], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "site_id_organization_fkey") org org? @relation(fields: [id_org], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "site_id_organization_fkey")
user user @relation(fields: [id_user], references: [id], onDelete: NoAction, onUpdate: NoAction) user user @relation(fields: [id_user], references: [id], onDelete: NoAction, onUpdate: NoAction)
site_plugin site_plugin[]
site_query site_query[] site_query site_query[]
} }
model site_plugin {
id_site String @db.Uuid
id_plugin String @db.Uuid
config Json
plugin plugin @relation(fields: [id_plugin], references: [id], onDelete: NoAction, onUpdate: NoAction)
site site @relation(fields: [id_site], references: [id], onDelete: NoAction, onUpdate: NoAction)
@@id([id_site, id_plugin], map: "id_site_plugin")
}
model site_query { model site_query {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
id_site String? @db.Uuid id_site String? @db.Uuid
@ -274,41 +161,11 @@ model user {
token_reset_password_expired DateTime? @db.Timestamp(6) token_reset_password_expired DateTime? @db.Timestamp(6)
updated_at DateTime? @default(now()) @db.Timestamp(6) updated_at DateTime? @default(now()) @db.Timestamp(6)
nominal_deposit Decimal @default(0) @db.Decimal(18, 3) nominal_deposit Decimal @default(0) @db.Decimal(18, 3)
billing_account billing_account[]
invoice invoice[]
org org[] org org[]
org_user org_user[] org_user org_user[]
site site[] site site[]
} }
model code {
id String @id(map: "code_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
id_site String @db.Uuid
name String @default("site")
site site @relation(fields: [id_site], references: [id], onDelete: Cascade, onUpdate: NoAction)
code_assign code_assign[]
code_file code_file[]
}
model code_file {
path String
content String
id_code String @db.Uuid
code code @relation(fields: [id_code], references: [id], onDelete: Cascade, onUpdate: NoAction)
@@id([path, id_code], map: "id_code_file")
}
model code_assign {
id_code String @db.Uuid
id_component_group String? @db.Uuid
id_page String? @db.Uuid
id String @id(map: "code_assign_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
code code @relation(fields: [id_code], references: [id], onDelete: Cascade, onUpdate: NoAction)
component_group component_group? @relation(fields: [id_component_group], references: [id], onDelete: NoAction, onUpdate: NoAction)
page page? @relation(fields: [id_page], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model page_history { model page_history {
id String @id(map: "page_history_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid id String @id(map: "page_history_id") @default(dbgenerated("gen_random_uuid()")) @db.Uuid
id_page String @db.Uuid id_page String @db.Uuid

View File

@ -81,7 +81,7 @@ export const EdCompPicker = () => {
> >
<div <div
dangerouslySetInnerHTML={{ dangerouslySetInnerHTML={{
__html: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" fill="none" viewBox="0 0 15 15"><path fill="currentColor" fill-rule="evenodd" d="M2 1a1 1 0 00-1 1v11a1 1 0 001 1h11a1 1 0 001-1V2a1 1 0 00-1-1H2zm0 1h11v11H2V2zm2.5 2a.5.5 0 00-.5.5v6a.5.5 0 00.5.5h6a.5.5 0 00.5-.5v-6a.5.5 0 00-.5-.5h-6zm.5 6V5h5v5H5z" clip-rule="evenodd"></path></svg>`, __html: `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-plus-2"><path d="M4 22h14a2 2 0 0 0 2-2V7l-5-5H6a2 2 0 0 0-2 2v4"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M3 15h6"/><path d="M6 12v6"/></svg>`,
}} }}
></div> ></div>
</TopBtn> </TopBtn>

View File

@ -3,18 +3,15 @@ import { useGlobal, useLocal } from "web-utils";
import { isLocalhost } from "../../../../../utils/ui/is-localhost"; import { isLocalhost } from "../../../../../utils/ui/is-localhost";
import { Loading } from "../../../../../utils/ui/loading"; import { Loading } from "../../../../../utils/ui/loading";
import { Modal } from "../../../../../utils/ui/modal"; import { Modal } from "../../../../../utils/ui/modal";
import { Popover } from "../../../../../utils/ui/popover";
import { Tooltip } from "../../../../../utils/ui/tooltip"; import { Tooltip } from "../../../../../utils/ui/tooltip";
import { EDGlobal } from "../../../logic/ed-global"; import { EDGlobal } from "../../../logic/ed-global";
import { import {
iconChevronDown,
iconDownload, iconDownload,
iconNewTab, iconNewTab,
iconScrollOff, iconScrollOff,
iconScrollOn, iconScrollOn,
iconUpload, iconUpload
} from "./icons"; } from "./icons";
import { CodeNameItem, CodeNameList } from "./name-list";
export const code = { export const code = {
mode: "" as "" | "old" | "new", mode: "" as "" | "old" | "new",
@ -33,16 +30,12 @@ export const EdPopCode = () => {
useEffect(() => { useEffect(() => {
if (code.mode === "" && p.site.id) { if (code.mode === "" && p.site.id) {
_db.code.findFirst({ where: { id_site: p.site.id } }).then((e) => {
code.mode = e ? "new" : "old";
if (localStorage.vsc_opened === "yes") { if (localStorage.vsc_opened === "yes") {
localStorage.removeItem("vsc_opened"); localStorage.removeItem("vsc_opened");
p.ui.popup.code.open = true; p.ui.popup.code.open = true;
} }
p.render(); p.render();
});
} }
}, [p.site.id]); }, [p.site.id]);
@ -77,35 +70,7 @@ export const EdPopCode = () => {
<div <div
className={cx("bg-white select-none fixed inset-[50px] bottom-0 flex")} className={cx("bg-white select-none fixed inset-[50px] bottom-0 flex")}
> >
{!code.mode && <Loading note="checking-version" backdrop={false} />} <CodeBody />
{code.mode === "new" && <CodeBody />}
{code.mode === "old" && (
<div className="flex items-center justify-center flex-col flex-1">
<div>This site still using old code</div>
<div
onClick={() => {
if (
confirm(
"Old code will not load, are you sure want to upgrade ?"
)
) {
code.mode = "new";
_db.code.create({
data: { id_site: p.site.id, name: "site" },
});
p.ui.popup.code.open = false;
p.render();
}
}}
className="border border-blue-500 cursor-pointer bg-blue-100 p-2 hover:bg-blue-200"
>
Upgrade to New Code Project
</div>
<div className="text-xs py-2">
Warning: old code will not load once upgraded.
</div>
</div>
)}
</div> </div>
</Modal> </Modal>
); );
@ -128,69 +93,6 @@ const CodeBody = () => {
<div className="relative w-full h-full flex flex-col"> <div className="relative w-full h-full flex flex-col">
<div className="border-b flex justify-between h-[40px] items-stretch"> <div className="border-b flex justify-between h-[40px] items-stretch">
<div className="flex items-stretch"> <div className="flex items-stretch">
{/* <Popover
placement="bottom"
offset={0}
arrow={false}
backdrop={false}
content={
<CodeNameList
onPick={async (e) => {
local.namePicker = false;
p.ui.popup.code.name = e.name;
p.render();
}}
/>
}
popoverClassName="bg-white shadow-md"
className={cx(
"flex items-center px-2 w-[200px] hover:bg-blue-50 space-x-1",
"cursor-pointer justify-between border-r "
)}
open={local.namePicker}
onOpenChange={(open) => {
local.namePicker = open;
local.render();
}}
>
<div className="capitalize overflow-ellipsis flex-1 flex items-center space-x-2">
<CodeNameItem name={p.ui.popup.code.name} />
</div>
<div
dangerouslySetInnerHTML={{
__html: iconChevronDown,
}}
></div>
</Popover> */}
{/* <Tooltip
content="STDOUT Log"
delay={0}
placement="bottom"
className={cx(
"flex items-stretch relative border-l",
p.ui.popup.code.error && "bg-red-500 text-white"
)}
onClick={() => {
p.ui.popup.code.show_log = !p.ui.popup.code.show_log;
p.render();
}}
>
{p.ui.popup.code.show_log && (
<div className="absolute bottom-[-4px] left-0 right-[1px] h-[5px] bg-white"></div>
)}
<div
className={cx(
"border-r flex text-center items-center hover:bg-blue-50 cursor-pointer px-2 transition-all",
p.ui.popup.code.loading
? "border-b-2 border-b-orange-400"
: "border-b-2 border-b-transparent"
)}
dangerouslySetInnerHTML={{
__html: p.ui.popup.code.loading ? iconLog : iconLoading,
}}
></div>
</Tooltip> */}
{p.ui.popup.code.startup_status !== "disabled" && ( {p.ui.popup.code.startup_status !== "disabled" && (
<Tooltip <Tooltip
content={`Startup Script: ${p.ui.popup.code.startup_status}`} content={`Startup Script: ${p.ui.popup.code.startup_status}`}

View File

@ -1,153 +0,0 @@
import { FC, useEffect } from "react";
import { useGlobal, useLocal } from "web-utils";
import { EDGlobal } from "../../../logic/ed-global";
import { iconModule, iconPlus, iconSSR, iconSite } from "./icons";
import { Popover } from "../../../../../utils/ui/popover";
export const codeName = {
loading: false,
list: [] as { name: string; id: string }[],
};
export const CodeNameItem: FC<{ name: string }> = ({ name }) => {
let className = "";
if (name === "site") {
className = css`
border-left: 4px solid #015fb8;
margin-left: -4px;
height: 18px;
`;
}
if (name === "SSR") {
className = css`
border-left: 4px solid #4dcfe0;
margin-left: -4px;
height: 18px;
`;
}
return (
<>
<div className={className}></div>
<NameIcon name={name} />
<span>{name === "site" ? "Main Site" : name}</span>
</>
);
};
export const CodeNameList: FC<{
onPick: (mod: { name: string; id: string }) => void;
}> = ({ onPick }) => {
const p = useGlobal(EDGlobal, "EDITOR");
const local = useLocal(
{
newname: "",
newopen: false,
},
async () => {
codeName.loading = true;
codeName.list = await _api.code(p.site.id, "list");
codeName.loading = false;
local.render();
}
);
return (
<>
<div className="w-[200px] border border-b-0 flex flex-col text-sm">
{codeName.list.length === 0 && (
<div className="border-b cursor-pointer px-2 py-[3px] capitalize items-center hover:bg-blue-100 flex space-x-2">
Loading...
</div>
)}
{codeName.list.map((e) => (
<div
key={e.id}
className="border-b cursor-pointer px-2 py-[3px] capitalize items-center hover:bg-blue-100 flex space-x-2"
onClick={() => {
onPick(e);
}}
>
<CodeNameItem name={e.name} />
</div>
))}
<Popover
open={local.newopen}
onOpenChange={(open) => {
if (open) {
local.newname = "";
}
local.newopen = open;
local.render();
}}
content={
<input
type="text"
className="outline-none pl-2 py-1 min-w[200px] text-sm"
placeholder="New Module Name"
value={local.newname}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.currentTarget.blur();
}
}}
spellCheck={false}
onBlur={async (e) => {
local.newopen = false;
local.render();
const nc = await _db.code.create({
data: {
id_site: p.site.id,
name: local.newname,
},
});
codeName.list.push({
name: nc.name,
id: nc.id,
});
local.render();
}}
onChange={(e) => {
local.newname = e.currentTarget.value
.toLowerCase()
.replace(/\W/gi, "-");
local.render();
}}
/>
}
autoFocus
popoverClassName="p-0 shadow-lg"
placement="right"
>
<div className="border-b cursor-pointer px-2 py-[3px] capitalize items-center flex space-x-2 hover:bg-green-100">
<span dangerouslySetInnerHTML={{ __html: iconPlus }}></span>
<span>New Code Module</span>
</div>
</Popover>
</div>
</>
);
};
export const NameIcon: FC<{ name: string; className?: string }> = ({
name,
className,
}) => {
const n = name.toLowerCase();
let html = "";
if (n === "site") {
html = iconSite;
} else if (n === "ssr") {
html = iconSSR;
} else {
html = iconModule;
}
return (
<div
className={cx(className)}
dangerouslySetInnerHTML={{ __html: html }}
></div>
);
};