mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-05-19 16:13:19 +00:00
Merge branch 'main' of github.com:supermemoryai/supermemory
This commit is contained in:
commit
0a4fa0da15
6 changed files with 157 additions and 50 deletions
|
|
@ -134,10 +134,6 @@ Built with:
|
|||
Yes, everything is free & open source.
|
||||
Supermemory is built by [me](https://dhravya.dev), a college student. My life situations make it very difficult and almost impossible to monetise the product.
|
||||
|
||||
Any kind of sponsorships / support would mean a lot to me, and help me keep supermemory alive.
|
||||
|
||||
You can sponsor on my Github sponsors page - https://github.com/sponsors/dhravya
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#Dhravya/supermemory&Date)
|
||||
|
|
@ -167,7 +163,7 @@ Thanks to all the awesome people who have contributed to supermemory.
|
|||
|
||||
## Sponsors
|
||||
|
||||
We are grateful for the support of our sponsors:
|
||||
We are grateful for the support of our supporters:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -717,9 +717,8 @@ const actions = fromHono(new Hono<{ Variables: Variables; Bindings: Env }>())
|
|||
return c.json({ error: "You must be logged in to add content" }, 401);
|
||||
}
|
||||
|
||||
const type = body.prefetched
|
||||
? Ok(body.prefetched.type)
|
||||
: typeDecider(body.content);
|
||||
// Do not perform seperate check for prefetched type, breaks tweet addition from extension
|
||||
const type = typeDecider(body.content);
|
||||
|
||||
if (isErr(type)) {
|
||||
return c.json(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
*, ::before, ::after {
|
||||
*,
|
||||
::before,
|
||||
::after {
|
||||
--tw-border-spacing-x: 0;
|
||||
--tw-border-spacing-y: 0;
|
||||
--tw-translate-x: 0;
|
||||
|
|
@ -130,7 +132,7 @@
|
|||
|
||||
::before,
|
||||
::after {
|
||||
--tw-content: '';
|
||||
--tw-content: "";
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -152,9 +154,11 @@ html,
|
|||
-moz-tab-size: 4;
|
||||
/* 3 */
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
tab-size: 4;
|
||||
/* 3 */
|
||||
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family:
|
||||
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
/* 4 */
|
||||
font-feature-settings: normal;
|
||||
/* 5 */
|
||||
|
|
@ -197,7 +201,7 @@ Add the correct text decoration in Chrome, Edge, and Safari.
|
|||
|
||||
abbr:where([title]) {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -243,7 +247,9 @@ code,
|
|||
kbd,
|
||||
samp,
|
||||
pre {
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
font-family:
|
||||
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
|
||||
"Courier New", monospace;
|
||||
/* 1 */
|
||||
font-feature-settings: normal;
|
||||
/* 2 */
|
||||
|
|
@ -344,9 +350,9 @@ select {
|
|||
*/
|
||||
|
||||
button,
|
||||
input:where([type='button']),
|
||||
input:where([type='reset']),
|
||||
input:where([type='submit']) {
|
||||
input:where([type="button"]),
|
||||
input:where([type="reset"]),
|
||||
input:where([type="submit"]) {
|
||||
-webkit-appearance: button;
|
||||
/* 1 */
|
||||
background-color: transparent;
|
||||
|
|
@ -393,7 +399,7 @@ Correct the cursor style of increment and decrement buttons in Safari.
|
|||
2. Correct the outline style in Safari.
|
||||
*/
|
||||
|
||||
[type='search'] {
|
||||
[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
/* 1 */
|
||||
outline-offset: -2px;
|
||||
|
|
@ -486,7 +492,8 @@ textarea {
|
|||
2. Set the default placeholder color to the user's configured gray 400 color.
|
||||
*/
|
||||
|
||||
input::-moz-placeholder, textarea::-moz-placeholder {
|
||||
input::-moz-placeholder,
|
||||
textarea::-moz-placeholder {
|
||||
opacity: 1;
|
||||
/* 1 */
|
||||
color: #9ca3af;
|
||||
|
|
@ -583,7 +590,9 @@ video {
|
|||
|
||||
body {
|
||||
background-color: hsl(var(--background));
|
||||
font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family:
|
||||
ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol", "Noto Color Emoji";
|
||||
color: hsl(var(--foreground));
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
|
@ -826,21 +835,29 @@ body {
|
|||
|
||||
.translate-x-\[-50\%\] {
|
||||
--tw-translate-x: -50%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.translate-y-\[-50\%\] {
|
||||
--tw-translate-y: -50%;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.rotate-180 {
|
||||
--tw-rotate: 180deg;
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
.transform {
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
transform: translate(var(--tw-translate-x), var(--tw-translate-y))
|
||||
rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y))
|
||||
scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
|
|
@ -859,8 +876,8 @@ body {
|
|||
|
||||
.select-none {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.flex-col {
|
||||
|
|
@ -1323,26 +1340,39 @@ body {
|
|||
|
||||
.shadow {
|
||||
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
--tw-shadow-colored:
|
||||
0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-lg {
|
||||
--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
--tw-shadow:
|
||||
0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored:
|
||||
0 10px 15px -3px var(--tw-shadow-color),
|
||||
0 4px 6px -4px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-md {
|
||||
--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
--tw-shadow-colored:
|
||||
0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
|
||||
.shadow-sm {
|
||||
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000),
|
||||
var(--tw-shadow);
|
||||
}
|
||||
|
||||
.outline-none {
|
||||
|
|
@ -1359,7 +1389,9 @@ body {
|
|||
}
|
||||
|
||||
.filter {
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast)
|
||||
var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate)
|
||||
var(--tw-sepia) var(--tw-drop-shadow);
|
||||
}
|
||||
|
||||
.transition-all {
|
||||
|
|
@ -1369,7 +1401,8 @@ body {
|
|||
}
|
||||
|
||||
.transition-colors {
|
||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
||||
transition-property:
|
||||
color, background-color, border-color, text-decoration-color, fill, stroke;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 150ms;
|
||||
}
|
||||
|
|
@ -1468,9 +1501,13 @@ body {
|
|||
}
|
||||
|
||||
.focus\:ring-2:focus {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
|
||||
var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0
|
||||
calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
|
||||
var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.focus\:ring-ring:focus {
|
||||
|
|
@ -1487,9 +1524,13 @@ body {
|
|||
}
|
||||
|
||||
.focus-visible\:ring-1:focus-visible {
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
|
||||
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0
|
||||
var(--tw-ring-offset-width) var(--tw-ring-offset-color);
|
||||
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0
|
||||
calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
|
||||
box-shadow:
|
||||
var(--tw-ring-offset-shadow), var(--tw-ring-shadow),
|
||||
var(--tw-shadow, 0 0 #0000);
|
||||
}
|
||||
|
||||
.focus-visible\:ring-ring:focus-visible {
|
||||
|
|
@ -1579,7 +1620,9 @@ body {
|
|||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
|
||||
.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0 [cmdk-group]:not([hidden]) ~[cmdk-group] {
|
||||
.\[\&_\[cmdk-group\]\:not\(\[hidden\]\)_\~\[cmdk-group\]\]\:pt-0
|
||||
[cmdk-group]:not([hidden])
|
||||
~ [cmdk-group] {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,11 +91,13 @@ function Navbar({ user }: { user?: User }) {
|
|||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
{/* TODO: Add profile modal */}
|
||||
{/* <ProfileModal>
|
||||
<DropdownMenuItem>
|
||||
<UserIcon className="mr-2 h-4 w-4" />
|
||||
<span>Profile</span>
|
||||
<DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
|
||||
</DropdownMenuItem>
|
||||
</ProfileModal> */}
|
||||
<DropdownMenuItem onSelect={toggleTheme}>
|
||||
{theme === Theme.LIGHT ? (
|
||||
<Sun className="mr-2 h-4 w-4" />
|
||||
|
|
@ -105,13 +107,13 @@ function Navbar({ user }: { user?: User }) {
|
|||
<span>{theme === Theme.LIGHT ? "Dark mode" : "Light mode"}</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem asChild>
|
||||
<a href="https://portal.productboard.com/8rhspck6pdelv78mptczaena" target="_blank">
|
||||
<a href="https://portal.productboard.com/8rhspck6pdelv78mptczaena" target="_blank" rel="noreferrer">
|
||||
<LifeBuoy className="mr-2 h-4 w-4" />
|
||||
<span>Support</span>
|
||||
</a>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem asChild>
|
||||
<a href="https://api.supermemory.ai" target="_blank">
|
||||
<a href="https://api.supermemory.ai" target="_blank" rel="noreferrer">
|
||||
<Cloud className="mr-2 h-4 w-4" />
|
||||
<span>API</span>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ export function AddMemoryModal({
|
|||
activeTab === "integrations" && "lg:col-span-3",
|
||||
)}
|
||||
>
|
||||
<TabsList className="border md:flex-col md:h-full h-max md:justify-start md:space-y-2 bg-[#FAFBFC] dark:bg-zinc-800 md:col-span-1 p-2 flex flex-row justify-between overflow-x-auto md:overflow-visible shrink-0">
|
||||
<TabsList className="border md:flex-col md:h-full h-max md:justify-start md:space-y-2 bg-[#FAFBFC] dark:bg-zinc-800 md:col-span-1 p-2 flex flex-row justify-between overflow-x-auto md:overflow-y-scroll shrink-0">
|
||||
<TabsTrigger
|
||||
className="w-full justify-start text-left px-4 py-3 rounded-lg border border-transparent data-[state=active]:border-indigo-500/20 data-[state=active]:bg-indigo-500/10 hover:bg-zinc-100 dark:hover:bg-zinc-700 flex flex-col items-start gap-2 transition-all duration-200 hover:shadow-sm"
|
||||
id="url-tab"
|
||||
|
|
@ -458,7 +458,7 @@ export function AddMemoryModal({
|
|||
)}
|
||||
</CredenzaBody>
|
||||
<CredenzaFooter className="border-t">
|
||||
<div className="flex justify-between w-full">
|
||||
<div className="flex justify-between w-full pt-2">
|
||||
<CredenzaClose asChild>
|
||||
<Button id="close-memory-modal" variant="outline">
|
||||
Cancel
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@
|
|||
|
||||
--chart-5: 340 75% 55%;
|
||||
}
|
||||
[data-registry="plate"] {
|
||||
[data-registry="plate"] {
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 240 10% 3.9%;
|
||||
--card: 0 0% 100%;
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
--brand: 217.2 91.2% 59.8%;
|
||||
--highlight: 47.9 95.8% 53.1%;
|
||||
}
|
||||
[data-registry="plate"].dark {
|
||||
[data-registry="plate"].dark {
|
||||
--background: 240 10% 3.9%;
|
||||
--foreground: 0 0% 98%;
|
||||
--card: 240 10% 3.9%;
|
||||
|
|
@ -184,3 +184,70 @@
|
|||
@apply absolute bottom-0 left-0 right-0 h-12 bg-gradient-to-t from-card to-transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/* Base state - scrollbar always present but invisible */
|
||||
.md\:overflow-y-scroll::-webkit-scrollbar {
|
||||
width: 4px; /* Thin scrollbar */
|
||||
background-color: transparent;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.md\:overflow-y-scroll::-webkit-scrollbar-track {
|
||||
background-color: rgba(240, 240, 240, 0.1); /* Very subtle light track in light mode */
|
||||
}
|
||||
|
||||
.md\:overflow-y-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(155, 155, 155, 0.5); /* Light gray thumb */
|
||||
border-radius: 10px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
/* Show scrollbar on hover */
|
||||
.md\:overflow-y-scroll:hover::-webkit-scrollbar,
|
||||
.md\:overflow-y-scroll:hover::-webkit-scrollbar-thumb {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Dark mode adjustments */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.md\:overflow-y-scroll::-webkit-scrollbar-track {
|
||||
background-color: rgba(50, 50, 50, 0.1); /* Subtle dark track in dark mode */
|
||||
}
|
||||
|
||||
.md\:overflow-y-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(180, 180, 180, 0.5); /* Slightly lighter thumb for dark mode */
|
||||
}
|
||||
}
|
||||
|
||||
/* For Firefox */
|
||||
.md\:overflow-y-scroll {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(155, 155, 155, 0) transparent; /* Start with opacity 0 */
|
||||
transition: scrollbar-color 0.2s ease;
|
||||
}
|
||||
|
||||
.md\:overflow-y-scroll:hover {
|
||||
scrollbar-color: rgba(155, 155, 155, 0.5) rgba(240, 240, 240, 0.1); /* Light mode colors */
|
||||
}
|
||||
|
||||
/* Dark mode for Firefox */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.md\:overflow-y-scroll:hover {
|
||||
scrollbar-color: rgba(180, 180, 180, 0.5) rgba(50, 50, 50, 0.1); /* Dark mode colors */
|
||||
}
|
||||
}
|
||||
|
||||
/* For your specific dark mode class */
|
||||
.dark .md\:overflow-y-scroll::-webkit-scrollbar-track {
|
||||
background-color: rgba(50, 50, 50, 0.1);
|
||||
}
|
||||
|
||||
.dark .md\:overflow-y-scroll::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(180, 180, 180, 0.5);
|
||||
}
|
||||
|
||||
.dark .md\:overflow-y-scroll:hover {
|
||||
scrollbar-color: rgba(180, 180, 180, 0.5) rgba(50, 50, 50, 0.1);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue