Skip to content

Commit

Permalink
fix async store
Browse files Browse the repository at this point in the history
update README.md
  • Loading branch information
riccardoperra committed Nov 11, 2024
1 parent 85abaeb commit d7a5c38
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 106 deletions.
39 changes: 22 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ by allowing users to visualize, create and update existing CI/CD workflows.
> and [Appwrite’s Hacktoberfest 2024 Hackathon](https://appwrite.io/blog/post/appwrite-hacktoberfest-hackathon-2024).
>
> Although there are some alternative solutions that can help a lot writing workflow files
> directly from IDE, a core principle to this work was discovering new technologies and apply them for an MVP.
> directly from IDE, this project mainly is a MVP to discover new technologies
>
> The amount of time dedicated is very limited (around ~4 weekends, starting from 1st of October), and the features needed for a complete project are numerous.
> The amount of time dedicated in this project is very limited, and the features needed for a complete project are numerous.
> Therefore, some features will **undoubtedly be missing** and may be implemented in the future.
## Disclaimer for hackathon entry
Expand All @@ -34,7 +34,7 @@ Since they have two different deadlines, development will be subdivided into two

Those two branches are linked in a multi-environment railway project which is currently visible to everyone: [Railway Deployment](https://railway.app/project/8e131c67-73c1-4ab6-9fa4-31dfa6c9000e).

GitHub workflow that deploy the app: [deploy.yml](https://github.com/riccardoperra/pipelineui/blob/main/.github/workflows/deploy.yml#L10)
GitHub workflow that deploy the app: [deploy.yml](https://github.com/riccardoperra/pipelineui/blob/main/.github/workflows/deploy.yml)

Github environment deployments:

Expand All @@ -44,6 +44,7 @@ Github environment deployments:
## Table of contents

- [Features](#features)
- [Available editor features](./packages/app/src/routes/about/supported-workflow-features.mdx)
- [Technical info](#-technical-info)
- [UI](#ui)
- [YAML Editor](#yaml-editor)
Expand Down Expand Up @@ -88,14 +89,16 @@ Workflow files are persisted into [AppWrite Cloud](https://appwrite.io/) and **a
PipelineUI is entirely built with [Solid](https://github.com/solidjs/solid) and [SolidStart](https://github.com/solidjs/solid-start)
with enabled SSR.

The core features of this project can be summarized in a few points:
The core technical points of this project can be summarized in those bullet items:

- SolidStart server fns calls for session, workflow retrieval and scratches crud
- SolidStart mutations and server actions
- Appwrite OAuth integration with SolidStart api routes
- Appwrite Database integration with SolidStart server function
- CodeMirror with LSP via web-worker and linter integration
- MDX routes for /about pages
- SolidStart SSR with mutations and server functions for session, workflow and scratches crud
- Language Service Protocol and Linter integration with CodeMirror via web-worker
- MDX prerendered routes for /about pages
- [About](https://pipelineui.dev/about)
- [Supported workflow features](https://pipelineui.dev/about/supported-workflow-features)
- Editor local first state management with statebuilder via plugin, with YAML synchronization
- Appwrite OAuth integration with SolidStart API routes
- Appwrite Database integration with SolidStart server functions

### User interface

Expand Down Expand Up @@ -143,7 +146,7 @@ The user interface has been built with:

### Flow diagram

The implemented Flow diagram is very limited and it has been built with solid taking advantage of some other dependencies:
The implemented Flow diagram is very basic and it has been built with solid taking advantage of some other dependencies:

- [elkjs](https://github.com/kieler/elkjs): ELK layout algorithm, used to calculate the flow item positions
- [panzoom](https://github.com/anvaka/panzoom): Cross-browser compatible pan and zoom library
Expand All @@ -155,25 +158,27 @@ The implemented Flow diagram is very limited and it has been built with solid ta

### Backend

Backend has been built with [appwrite](https://appwrite.io/), which has been wrapped via solid server functions
to provide authentication and the database persistence.
Backend persistence and authentication has been done with [appwrite](https://appwrite.io/).

Used Appwrite features:

- Auth
- Database

Most of the code is available into [packages/app/lib/server](packages/app/src/lib/server).
Most of the Appwrite code is available into

- [packages/app/src/lib/server](packages/app/src/lib/server).
- [packages/app/src/lib/scratchApi.ts](packages/app/src/lib/scratchApi.ts).
- [packages/app/src/routes/api/oauth.ts](packages/app/src/routes/api/oauth.ts).

---

### Other dependencies

This projects also uses some of mine older dependencies that were used to speed up the development.
These have also been updated to fix the bugs encountered.
Here's a list of my personal dependencies, which they have been used to be tested and improved during the development.

- [@codeui/kit](https://github.com/riccardoperra/codeui): [CodeImage](https://github.com/riccardoperra/codeimage) design
system which wraps Kobalte.
system (Kobalte + VanillaExtract)
- [statebuilder](https://github.com/riccardoperra/statebuilder): Pluggable state management
- [solid-codemirror](https://github.com/riccardoperra/solid-codemirror): SolidJS adapter for CodeMirror

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {For, useContext} from 'solid-js';
import {EditorContext} from '../editor.context';
import * as fallbackStyles from '~/ui/components/Fallback.css';

export function YamlEditorFallback() {
const editor = useContext(EditorContext);
return (
<div
style={{
'margin-top': '12px',
display: 'flex',
'flex-direction': 'column',
gap: '4px',
}}
>
<For each={editor?.source.split('\n')}>
{(row, index) => {
const match = row.match(/^(\s*)(\S.*)/)!;
const leadingWhitespace = match ? match[1] : row;
const text = match ? match[2] : null;

return (
<div
style={{display: 'flex', 'flex-wrap': 'nowrap', height: '16px'}}
>
<span
class={fallbackStyles.fallback}
style={{
'margin-left': '24px',
'margin-right': '16px',
'font-size': '13.5px',
'line-height': '14px',
}}
>
{String(index() + 1).padStart(3, '0')}
</span>
<span
style={{
'font-size': '13.5px',
'line-height': '17px',
'white-space': 'pre-wrap',
}}
>
{leadingWhitespace}
</span>
<span
style={{
'font-size': '13.5px',
'line-height': '17px',
'white-space': 'nowrap',
}}
class={fallbackStyles.fallback}
>
{text || leadingWhitespace}
</span>
</div>
);
}}
</For>
</div>
);
}
79 changes: 3 additions & 76 deletions packages/app/src/components/Editor/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
import Resizable from '@corvu/resizable';
import {
createEffect,
For,
lazy,
Match,
Show,
Suspense,
Switch,
useContext,
} from 'solid-js';
import {lazy, Match, Show, Suspense, Switch} from 'solid-js';
import {provideState} from 'statebuilder';
import * as fallbackStyles from '~/ui/components/Fallback.css';
import {OverlayLoader} from '~/ui/components/Loader/Loader';
import {EditorStore} from '../../store/editor/editor.store';
import {EditorUiStore} from '../../store/editor/ui.store';
import {YamlMergeView} from './CodeEditor/MergeView';
import {YamlEditorFallback} from './CodeEditor/YamlEditorFallback';
import {DiagnosticPanel} from './DiagnosticPanel/DiagnosticPanel';
import * as styles from './Editor.css';
import {EditorHeader} from './Header/Header';
Expand All @@ -24,8 +16,6 @@ import {EditorResizableHandler} from './layout/Resizable/Resizable';
import {EditorSidebar} from './LeftSidebar/EditorSidebar';
import {PropertiesPanelEditor} from './Properties/PropertiesPanelEditor';
import {EditorStatusBar} from './StatusBar/StatusBar';
import {YamlMergeView} from './CodeEditor/MergeView';
import {EditorContext} from './editor.context';

const YamlEditor = lazy(() =>
import('./CodeEditor/YamlEditor').then(m => ({default: m.YamlEditor})),
Expand All @@ -44,10 +34,6 @@ export function Editor(props: EditorProps) {
const editorUi = provideState(EditorUiStore);
const editor = provideState(EditorStore);

createEffect(() => {
console.log({props});
});

return (
<div class={styles.wrapper}>
<EditorHeader
Expand Down Expand Up @@ -219,62 +205,3 @@ export function Editor(props: EditorProps) {
</div>
);
}

function YamlEditorFallback() {
const editor = useContext(EditorContext);
return (
<div
style={{
'margin-top': '12px',
display: 'flex',
'flex-direction': 'column',
gap: '4px',
}}
>
<For each={editor?.source.split('\n')}>
{(row, index) => {
const match = row.match(/^(\s*)(\S.*)/)!;
const leadingWhitespace = match ? match[1] : row;
const text = match ? match[2] : null;

return (
<div
style={{display: 'flex', 'flex-wrap': 'nowrap', height: '16px'}}
>
<span
class={fallbackStyles.fallback}
style={{
'margin-left': '24px',
'margin-right': '16px',
'font-size': '13.5px',
'line-height': '14px',
}}
>
{String(index() + 1).padStart(3, '0')}
</span>
<span
style={{
'font-size': '13.5px',
'line-height': '17px',
'white-space': 'pre-wrap',
}}
>
{leadingWhitespace}
</span>
<span
style={{
'font-size': '13.5px',
'line-height': '17px',
'white-space': 'nowrap',
}}
class={fallbackStyles.fallback}
>
{text || leadingWhitespace}
</span>
</div>
);
}}
</For>
</div>
);
}
2 changes: 1 addition & 1 deletion packages/app/src/components/Editor/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function EditorHeaderForkButton() {
<Popover open={isOpen()} onOpenChange={setOpen}>
<PopoverTrigger
as={triggerProps => (
<Button theme={'primary'} {...triggerProps}>
<Button theme={'primary'} size={'sm'} {...triggerProps}>
{_(msg`Fork`)}
</Button>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const panelAccordionTrigger = style({
display: 'flex',
height: '36px',
alignItems: 'center',
fontWeight: 600,
gap: appTheme.spacing['2'],
paddingLeft: appTheme.spacing['3'],
background: `transparent`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function PanelAccordionItem(props: FlowProps<PanelAccordionItemProps>) {

{props.name}
</Accordion.Trigger>
<IconButton
<IconButton<'button'>
size={'xs'}
variant={'ghost'}
theme={'secondary'}
Expand Down
2 changes: 1 addition & 1 deletion packages/app/src/components/Home/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function HomeFooter() {
</A>
</div>
<span style={{color: '#ddd'}}>
{_(msg`Built with`)}
{_(msg`Built with`)}{' '}
<A class={footerLink} href="https://github.com/solidjs/solid">
Solid
</A>{' '}
Expand Down
4 changes: 3 additions & 1 deletion packages/app/src/global-codeui.css.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import {globalStyle, globalFontFace} from '@vanilla-extract/css';
import {themeVars} from '@codeui/kit';

import gabaritoFont from '/fonts/Gabarito-VariableFont_wght.ttf?inline';

globalFontFace('Gabarito', {
src: 'url(/fonts/Gabarito-VariableFont_wght.ttf)',
src: `url(${gabaritoFont})`,
});

globalStyle('[data-cui-theme=dark] html, body', {
Expand Down
42 changes: 33 additions & 9 deletions packages/app/src/lib/statebuilder/async.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import {AccessorWithLatest, createAsync} from '@solidjs/router';
import {createComputed, createSignal, on, Setter} from 'solid-js';
import {
createComputed,
createEffect,
createReaction,
createRenderEffect,
createRoot,
createSignal,
getOwner,
on,
onCleanup,
Owner,
Setter,
untrack,
} from 'solid-js';
import {create} from 'statebuilder';

export interface AsyncSignalState<T> {
Expand Down Expand Up @@ -28,20 +41,31 @@ function makeAsyncSignal<T>(
},
): AsyncSignalState<T | undefined> {
const asyncState = createAsync(fetcher, options);
const [mode, setMode] = createSignal<'auto' | 'manual'>('auto');
const [signal, setSignal] = createSignal<T | undefined>(
options?.initialValue,
);

createComputed(
on(asyncState, latest => {
// Sync latest signal retrieved by asyncState in order to be available globally after navigation
setSignal(() => latest);
}),
);
createEffect(() => {
setSignal(() => asyncState());
});

const value = () => {
const $mode = mode();
if ($mode === 'auto') {
return asyncState();
}
return signal();
};

const set: Setter<T | undefined> = ((arg0: any) => {
setMode('manual');
setSignal(arg0);
}) as Setter<T | undefined>;

const state: AsyncSignalState<T | undefined> = Object.assign(signal, {
const state: AsyncSignalState<T | undefined> = Object.assign(value, {
raw: asyncState,
set: setSignal,
set,
});

return state;
Expand Down

0 comments on commit d7a5c38

Please sign in to comment.