Skip to content

Commit

Permalink
Merge pull request #4077 from signalco-io/next
Browse files Browse the repository at this point in the history
Next
  • Loading branch information
AleksandarDev authored Dec 11, 2023
2 parents 4b29c58 + 3f81bc7 commit 42df9a8
Show file tree
Hide file tree
Showing 18 changed files with 122 additions and 105 deletions.
1 change: 0 additions & 1 deletion web/apps/app/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ const componsedNextConfig = withBundleAnalyzer(nextConfig);
const nextConfigFunction = async (phase) => {
if (phase === PHASE_DEVELOPMENT_SERVER || phase === PHASE_PRODUCTION_BUILD) {
const withPWA = (await import('@ducanh2912/next-pwa')).default({
dest: 'public',
buildExcludes: [/middleware-manifest.json$/, /chunks\/images\/.*$/],
dynamicStartUrl: false,
disable: isDevelopment
Expand Down
2 changes: 1 addition & 1 deletion web/apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
},
"devDependencies": {
"@axe-core/playwright": "4.8.2",
"@ducanh2912/next-pwa": "9.7.2",
"@ducanh2912/next-pwa": "10.0.0",
"@next/bundle-analyzer": "14.0.4",
"@playwright/test": "1.40.1",
"@signalco/eslint-config-signalco": "workspace:*",
Expand Down
4 changes: 1 addition & 3 deletions web/apps/doprocess/app/(rest)/(app)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { PropsWithChildren } from 'react';
import { AppProviders } from '../../../components/providers/AppProviders';
import { PageNav } from '../../../components/PageNav';
import { AppLayout } from '../../../components/layouts/AppLayout';

export default function RootLayout({ children }: PropsWithChildren) {
return (
<>
<PageNav fullWidth />
<div className="pt-16 md:h-full">
<div className="md:h-full">
<AppProviders>
<AppLayout>
{children}
Expand Down
2 changes: 1 addition & 1 deletion web/apps/doprocess/app/(rest)/(marketing)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default function RootMarketingLayout({ children, }: {
}) {
return (
<>
<PageNav fullWidth cta />
<PageNav fullWidth />
<Container className="pt-20" maxWidth="lg">
{children}
</Container>
Expand Down
2 changes: 1 addition & 1 deletion web/apps/doprocess/app/api/documents/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { documentCreate, documentGet, documentsGet, documentSetData } from '../../../src/lib/repo/documentsRepository';
import { documentCreate, documentGet, documentsGet } from '../../../src/lib/repo/documentsRepository';
import { ensureUserId } from '../../../src/lib/auth/apiAuth';

export async function GET() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,35 @@ export async function PUT(request: Request, { params }: { params: { id: string,

const data = await request.json();
if (data != null && typeof data === 'object') {
// Update text (name)
if ('text' in data && typeof data.text === 'string') {
await changeTaskDefinitionText(userId, processId, taskDefinitionId, data.text);
}

// Update type
if ('type' in data && typeof data.type === 'string') {
let typeData = 'typeData' in data && typeof data.typeData === 'string' ? data.typeData : null;
if (!typeData && data.type === 'document') {
const type = data.type;
let typeData = ('typeData' in data && typeof data.typeData === 'string') ? data.typeData : null;
if (!typeData && type === 'document') {
const process = await getProcess(userId, processId);
const taskDefinition = await getTaskDefinition(userId, processId, taskDefinitionId);
// TODO: Use publicId instead of internalId for dataType
const documentName = [process?.name, taskDefinition?.text ?? 'New document'].filter(Boolean).join(' - ');
const documentId = await documentCreate(userId, documentName);
const document = await documentGet(userId, Number(documentId));
const document = await documentGet(userId, documentId);
if (document) {
typeData = document?.publicId;
}
} else if (data.type === 'blank') {
} else if (type === 'blank') {
typeData = 'blank';
}
if (!typeData) {
throw new Error('Invalid type');
}

await changeTaskDefinitionType(userId, processId, taskDefinitionId, data.type, typeData);
await changeTaskDefinitionType(userId, processId, taskDefinitionId, type, typeData);
}

// Update order
if ('order' in data && typeof data.order === 'string') {
await changeTaskDefinitionOrder(userId, processId, taskDefinitionId, data.order);
}
Expand Down
16 changes: 7 additions & 9 deletions web/apps/doprocess/components/NavMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const navLinks: NavLinkItem[] = [
// { href: KnownPages.Pricing, text: 'Pricing' }
];

export function NavMenu({ cta }: { cta?: boolean; }) {
export function NavMenu() {
return (
<>
{navLinks.map(nl => (
Expand All @@ -31,14 +31,12 @@ export function NavMenu({ cta }: { cta?: boolean; }) {
<SignUpButton>Start for free</SignUpButton>
</SignedOut>
<SignedIn>
{cta && (
<Button
variant="solid"
href={KnownPages.Runs}
endDecorator={<Navigate />}>
Go to app
</Button>
)}
<Button
variant="solid"
href={KnownPages.Runs}
endDecorator={<Navigate />}>
App
</Button>
<UserButton afterSignOutUrl="/" />
</SignedIn>
</>
Expand Down
4 changes: 2 additions & 2 deletions web/apps/doprocess/components/PageNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { KnownPages } from '../src/knownPages';
import { NavMenu } from './NavMenu';
import DoProcessLogo from './brand/DoProcessLogo';

export function PageNav({ fullWidth, cta }: { fullWidth?: boolean, cta?: boolean }) {
export function PageNav({ fullWidth }: { fullWidth?: boolean }) {
return (
<nav className={cx(
'backdrop-blur-md fixed top-0 left-0 right-0 z-10 h-16 border-b flex items-center',
Expand All @@ -21,7 +21,7 @@ export function PageNav({ fullWidth, cta }: { fullWidth?: boolean, cta?: boolean
</Link>
</div>
<Row spacing={1}>
<NavMenu cta={cta} />
<NavMenu />
</Row>
</Row>
</header>
Expand Down
21 changes: 9 additions & 12 deletions web/apps/doprocess/components/layouts/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

import { useEffect, useMemo } from 'react';
import { usePathname } from 'next/navigation';
import { Typography } from '@signalco/ui-primitives/Typography';
import { ListItem } from '@signalco/ui-primitives/ListItem';
import { List } from '@signalco/ui-primitives/List';
import { IconButton } from '@signalco/ui-primitives/IconButton';
import { cx } from '@signalco/ui-primitives/cx';
import { FileText, ListTodo, Play, Right } from '@signalco/ui-icons';
import { FileText, ListTodo, Play } from '@signalco/ui-icons';
import { UserButton } from '../auth/UserButton';
import { KnownPages } from '../../src/knownPages';

export function Sidebar({ open, onOpenChange }: { open: boolean, onOpenChange?: (open: boolean) => void }) {
Expand All @@ -29,16 +30,12 @@ export function Sidebar({ open, onOpenChange }: { open: boolean, onOpenChange?:
'group flex flex-row -mr-1 border-b md:h-full md:flex-col md:border-none',
open && 'md:pl-2 md:gap-1'
)}>
<IconButton
variant="plain"
className={cx(
open ? 'opacity-0 rotate-180 rounded-bl-none' : 'rounded-tr-none',
'hidden md:block self-end text-muted-foreground transition-opacity group-hover:opacity-100'
)}
size="sm"
onClick={() => onOpenChange?.(!open)}>
<Right size={16} />
</IconButton>
<div className="flex flex-row items-center justify-between p-2">
{open && <Typography semiBold tertiary level="body2" className="hidden md:block">Navigation</Typography>}
<div className="px-0.5">
<UserButton afterSignOutUrl="/" />
</div>
</div>
<List className={cx('flex-row md:flex-col', open && 'md:gap-2 md:pr-2')}>
{links.map(({ href, label, Icon }) => (
<ListItem
Expand Down
1 change: 0 additions & 1 deletion web/apps/doprocess/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ const componsedNextConfig = withBundleAnalyzer(nextConfig);
const nextConfigFunction = async (phase) => {
if (phase === PHASE_DEVELOPMENT_SERVER || phase === PHASE_PRODUCTION_BUILD) {
const withPWA = (await import('@ducanh2912/next-pwa')).default({
dest: 'public',
buildExcludes: [/middleware-manifest.json$/, /chunks\/images\/.*$/],
dynamicStartUrl: false,
disable: isDevelopment,
Expand Down
2 changes: 1 addition & 1 deletion web/apps/doprocess/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"devDependencies": {
"@axe-core/playwright": "4.8.2",
"@babel/core": "7.23.5",
"@ducanh2912/next-pwa": "9.7.2",
"@ducanh2912/next-pwa": "10.0.0",
"@next/bundle-analyzer": "14.0.4",
"@playwright/test": "1.40.1",
"@signalco/eslint-config-signalco": "workspace:*",
Expand Down
14 changes: 9 additions & 5 deletions web/apps/doprocess/src/lib/db/schema.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { datetime, index, int, json, mysqlTable, serial, text, uniqueIndex, varchar } from 'drizzle-orm/mysql-core';
import { relations, sql } from 'drizzle-orm';

export const withPublicIdTable = {
publicId: varchar('public_id', { length: 32 }).notNull().unique(),
};

export const process = mysqlTable('process', {
id: serial('id').primaryKey(),
publicId: varchar('public_id', { length: 32 }).notNull().unique(),
...withPublicIdTable,
name: varchar('name', { length: 255 }).notNull(),
sharedWithUsers: json('shared_with_users').$type<string[]>().notNull(),
createdBy: varchar('created_by', { length: 255 }).notNull(),
Expand All @@ -18,7 +22,7 @@ export type Process = typeof process.$inferSelect;

export const processRun = mysqlTable('process_run', {
id: serial('id').primaryKey(),
publicId: varchar('public_id', { length: 32 }).notNull().unique(),
...withPublicIdTable,
processId: int('process_id').notNull(),
name: varchar('name', { length: 255 }).notNull(),
state: varchar('state', { length: 255 }).notNull(),
Expand All @@ -35,7 +39,7 @@ export type ProcessRun = typeof processRun.$inferSelect;

export const taskDefinition = mysqlTable('task_definition', {
id: serial('id').primaryKey(),
publicId: varchar('public_id', { length: 32 }).notNull().unique(),
...withPublicIdTable,
processId: int('process_id').notNull(),
text: text('text'),
order: varchar('order', { length: 255 }).notNull(),
Expand All @@ -54,7 +58,7 @@ export type TaskDefinition = typeof taskDefinition.$inferSelect;

export const document = mysqlTable('document', {
id: serial('id').primaryKey(),
publicId: varchar('public_id', { length: 32 }).notNull().unique(),
...withPublicIdTable,
name: text('name').notNull(),
data: json('data'),
sharedWithUsers: json('shared_with_users').$type<string[]>().notNull(),
Expand All @@ -81,7 +85,7 @@ export const taskDefinitionRelations = relations(taskDefinition, ({ one }) => ({

export const task = mysqlTable('task', {
id: serial('id').primaryKey(),
publicId: varchar('public_id', { length: 32 }).notNull().unique(),
...withPublicIdTable,
processId: int('process_id').notNull(),
runId: int('run_id').notNull(),
taskDefinitionId: int('task_definition_id').notNull(),
Expand Down
34 changes: 28 additions & 6 deletions web/apps/doprocess/src/lib/repo/documentsRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,36 @@ import { document } from '../db/schema';
import { db } from '../db';
import { publicIdNext } from './shared';

function documentSharedWithUser(userId: string | null) {
if (!userId)
function documentSharedWithUser(userId: string | null, includePublic = true) {
if (!userId && includePublic)
return sql`"public" MEMBER OF(${document.sharedWithUsers})`;

if (userId && includePublic)
return sql`${userId} MEMBER OF(${document.sharedWithUsers})`;

return or(
sql`${userId} MEMBER OF(${document.sharedWithUsers})`,
sql`"public" MEMBER OF(${document.sharedWithUsers})`);
}

export async function getDocumentIdByPublicId(publicId: string) {
return firstOrDefault(await db.select({ id: document.id }).from(document).where(eq(document.publicId, publicId)))?.id;
return firstOrDefault(await db
.select({ id: document.id })
.from(document)
.where(
eq(document.publicId, publicId))
)?.id;
}

async function isDocumentSharedWithUser(userId: string, documentId: number) {
return (firstOrDefault(await db.select({ count: count() }).from(document).where(and(eq(document.id, documentId), documentSharedWithUser(userId))))?.count ?? 0) > 0;
return (firstOrDefault(await db
.select({ count: count() })
.from(document)
.where(
and(
eq(document.id, documentId),
documentSharedWithUser(userId)))
)?.count ?? 0) > 0;
}

export async function documentCreate(userId: string, name: string, basedOn?: string) {
Expand All @@ -35,6 +50,7 @@ export async function documentCreate(userId: string, name: string, basedOn?: str
if (basedOnId) {
const basedOnDocument = await documentGet(userId, basedOnId);
if (basedOnDocument && typeof basedOnDocument.data === 'string') {
console.info('Copying document content from (public):', basedOnDocument.publicId, 'to (internal):', id);
await documentSetData(userId, id, basedOnDocument.data);
}
}
Expand All @@ -44,11 +60,17 @@ export async function documentCreate(userId: string, name: string, basedOn?: str
}

export async function documentsGet(userId: string) {
return await db.select().from(document).where(documentSharedWithUser(userId));
return await db.select().from(document).where(documentSharedWithUser(userId, false));
}

export async function documentGet(userId: string | null, id: number) {
return firstOrDefault(await db.select().from(document).where(and(eq(document.id, id), documentSharedWithUser(userId))));
return firstOrDefault(await db
.select()
.from(document)
.where(
and(
eq(document.id, id),
documentSharedWithUser(userId))));
}

export async function documentRename(userId: string, id: number, name: string) {
Expand Down
33 changes: 26 additions & 7 deletions web/apps/doprocess/src/lib/repo/processesRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import { TaskState, process, processRun, task, taskDefinition } from '../db/sche
import { db } from '../db';
import { publicIdNext } from './shared';

function processSharedWithUser(userId: string | null) {
if (userId == null)
function processSharedWithUser(userId: string | null, includePublic = true) {
if (userId == null && includePublic)
return sql`"public" MEMBER OF(${process.sharedWithUsers})`

if (userId && !includePublic)
return sql`${userId} MEMBER OF(${process.sharedWithUsers})`;

return or(
sql`${userId} MEMBER OF(${process.sharedWithUsers})`,
sql`"public" MEMBER OF(${process.sharedWithUsers})`
Expand All @@ -19,7 +22,11 @@ async function isProcessSharedWithUser(userId: string | null, processId: number)
return (firstOrDefault(await db
.select({ count: count() })
.from(process)
.where(and(eq(process.id, processId), processSharedWithUser(userId))))?.count ?? 0) > 0;
.where(
and(
eq(process.id, processId),
processSharedWithUser(userId)))
)?.count ?? 0) > 0;
}

export async function getProcessIdByPublicId(publicId: string) {
Expand Down Expand Up @@ -51,7 +58,7 @@ export async function getProcessRunTaskIdByPublicId(processPublicId: string, pro
}

export async function getProcesses(userId: string) {
return await db.select().from(process).where(processSharedWithUser(userId));
return await db.select().from(process).where(processSharedWithUser(userId, false));
}

export async function getProcess(userId: string | null, processId: number) {
Expand Down Expand Up @@ -192,7 +199,13 @@ export async function getTaskDefinitions(userId: string | null, processId: numbe
export async function getTaskDefinition(userId: string | null, processId: number, taskDefinitionId: number) {
if (!await isProcessSharedWithUser(userId, processId))
throw new Error('Not found');
return firstOrDefault(await db.select().from(taskDefinition).where(and(eq(taskDefinition.processId, processId), eq(taskDefinition.id, taskDefinitionId))));
return firstOrDefault(await db
.select()
.from(taskDefinition)
.where(
and(
eq(taskDefinition.processId, processId),
eq(taskDefinition.id, taskDefinitionId))));
}

async function getTaskDefinitionLastOrder(userId: string, processId: number) {
Expand Down Expand Up @@ -223,11 +236,17 @@ export async function changeTaskDefinitionText(userId: string, processId: number
await db.update(taskDefinition).set({ text, updatedBy: userId, updatedAt: new Date() }).where(and(eq(taskDefinition.processId, processId), eq(taskDefinition.id, id)));
}

export async function changeTaskDefinitionType(userId: string, processId: number, id: number, type: string, typeData: string) {
export async function changeTaskDefinitionType(userId: string, processId: number, id: number, type: string, typeData: string | null) {
if (!await isProcessSharedWithUser(userId, processId))
throw new Error('Not found');
// TODO: Check permissions
await db.update(taskDefinition).set({ type, typeData, updatedBy: userId, updatedAt: new Date() }).where(and(eq(taskDefinition.processId, processId), eq(taskDefinition.id, id)));
await db
.update(taskDefinition)
.set({ type: type, typeData: typeData, updatedBy: userId, updatedAt: new Date() })
.where(
and(
eq(taskDefinition.processId, processId),
eq(taskDefinition.id, id)));
}

export async function changeTaskDefinitionOrder(userId: string, processId: number, id: number, order: string) {
Expand Down
Loading

7 comments on commit 42df9a8

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

signalco-app – ./web/apps/app

signalco-app-git-main-signalco.vercel.app
signalco-app.vercel.app
app.signalco.io
signalco-app-signalco.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

signalco-slco – ./web/apps/slco

slco.signalco.io
signalco-slco.vercel.app
signalco-slco-signalco.vercel.app
slco.io
signalco-slco-git-main-signalco.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

signalco-blog – ./web/apps/blog

signalco-blog-git-main-signalco.vercel.app
signalco-blog-signalco.vercel.app
signalco-blog.vercel.app
blog.signalco.io

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

signalco-ui-docs – ./web/apps/ui-docs

signalco-ui-docs.vercel.app
signalco-ui-docs-git-main-signalco.vercel.app
signalco-ui-docs-signalco.vercel.app
ui.signalco.io

@vercel
Copy link

@vercel vercel bot commented on 42df9a8 Dec 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.