Skip to content

Commit

Permalink
Merge pull request #476 from writer/dev
Browse files Browse the repository at this point in the history
chore: Merge for release
  • Loading branch information
ramedina86 committed Jun 25, 2024
2 parents 91a3ea0 + 73007b9 commit 3470f2e
Show file tree
Hide file tree
Showing 265 changed files with 14,971 additions and 8,706 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ src/ui/components.codegen.json
playground/
*.mp4
.turbo
styles.css
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## What is Writer Framework?
## What is Framework?

Writer Framework is an open-source framework for creating AI applications. Build user interfaces using a visual editor; write the backend code in Python.

Expand Down
1 change: 0 additions & 1 deletion alfred/ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ def ci(front, back, e2e, docs):
alfred.invoke_command("npm.lint")
alfred.invoke_command("npm.build")
if docs or no_flags:
alfred.invoke_command("npm.docs")
alfred.invoke_command("npm.docs.test")
if e2e:
alfred.invoke_command("npm.e2e", browser=e2e)
Expand Down
4 changes: 0 additions & 4 deletions alfred/npm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ def npm_build():
def npm_build_custom_components():
alfred.run("npm run ui:custom.build")

@alfred.command("npm.docs", help="build docs", hidden=True)
def npm_docs():
alfred.run("npm run docs:build")

@alfred.command("npm.docs.test", help="test against documentation")
def npm_docs_test():
alfred.run("npm run docs:test")
Expand Down
2 changes: 1 addition & 1 deletion alfred/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@alfred.command("run.docs", help="preview the documentation as a developper")
def run_docs():
os.chdir('docs')
alfred.run("npm run dev")
alfred.run("npm run preview")

@alfred.command("run.storybook", help="preview the storybook as a developper")
def run_storybook():
Expand Down
107 changes: 107 additions & 0 deletions docs/codegen/core.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Generates an example of component usage in Low Code
*
* @param component {object} Name of a component
* @returns Example code {string}
*
* @example
* component.low_code_usage = core.generateLowCodeUsage(component)
*/
export function generateLowCodeUsage(component) {
let contents = "content={\n"
for (let fieldKey in component.fields) {
const properties = component.fields[fieldKey]
contents += ` "${fieldKey}": ${renderDefaultValue(properties)}, # ${renderPyType(properties['type'])} ${renderPyOptions(properties['options'])}\n`
}
contents += " }"

let handlers = ""
if (component.events && Object.keys(component.events).length > 0) {
handlers += "\n,\n handlers={\n"
for (let event in component.events) {
handlers += ` "${event}": handle_event,\n`
}
handlers += " }"
}

// @ts-ignore
let code = `ui.${component.name.replaceAll(/\s/g, "")}(${contents.trim()}${handlers.trim()}
)`
return code
}

/**
*
* @example
* component.event_handler = core.generateEventHandler()
*/
export function generateEventHandler() {
let code = `def handle_event(state, payload, context, ui):
pass`
return code
}

/**
*
* @param obj {object}
* @returns {*[]}
*/
export function values(obj) {
if (!obj) return [];

return Object.keys(obj).map((key) => {
return obj[key]
})
}

/**
*
* @param properties {object}
* @returns {string}
*/
function renderDefaultValue(properties) {
const type = properties['type'];
switch (type) {
case "Number":
return '0.0';
case "Object":
return "{}";
case "Key-Value":
return "{}";
default:
if (properties['options'] && properties['default']) {
return `"${ properties['default'] }"`;
}

return '""';
}
}

/**
*
* @param type {string}
* @returns {string}
*/
const renderPyType = (type) => {
switch (type) {
case "Number":
return "Union[float, str]";
case "Object":
return "Union[Dict, str]";
case "Key-Value":
return "Union[Dict, str]";
default:
return "str";
}
};

/**
*
* @param options {object}
* @returns {string}
*/
const renderPyOptions = (options) => {
if (!options) return "";

return "[" + Object.keys(options).join(", ") + "]"
};
27 changes: 16 additions & 11 deletions docs/codegen/generator_components_pages.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,36 @@ import components from "writer-ui/components.codegen.json" with { type: "json" }
import * as fs from "fs";
import * as path from "path";
import { fileURLToPath } from "url";
import nunjucks from "nunjucks";
import * as core from "./core.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const docDirectory = path.resolve(__dirname, "..", "docs");
const docComponentsDirectory = path.resolve(docDirectory, "components");
const componentPageTemplate = path.resolve(
docComponentsDirectory,
"component_page.md.tpl",
);
// const frameworkDirectory = path.resolve(__dirname, "..", "framework");
const componentsDirectory = path.resolve(__dirname, "..", "components");


export async function generate() {
// eslint-disable-next-line no-console
console.log("generate doc components pages into", docComponentsDirectory);
console.log("generate doc components pages into", componentsDirectory);
nunjucks.configure({ autoescape: true });

if (!fs.existsSync(docComponentsDirectory)) {
fs.mkdirSync(docComponentsDirectory);
if (!fs.existsSync(componentsDirectory)) {
fs.mkdirSync(componentsDirectory);
}

components.map((component) => {
// eslint-disable-next-line prettier/prettier
const componentPath = path.resolve(docComponentsDirectory, `${component.type}.md`);
const componentPageTemplate = path.resolve(componentsDirectory, "component_page.mdx.tpl");
const page = fs.readFileSync(componentPageTemplate, "utf8");
const renderedPage = page.replace("@{component_name}", component.name);

component.low_code_usage = core.generateLowCodeUsage(component)
component.event_handler = core.generateEventHandler()

const renderedPage = nunjucks.renderString(page, component);

const componentPath = path.resolve(componentsDirectory, `${component.type}.mdx`);
fs.writeFileSync(componentPath, renderedPage);
});
}
Expand Down
3 changes: 3 additions & 0 deletions docs/components/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*
!.gitignore
!component_page.mdx.tpl
74 changes: 74 additions & 0 deletions docs/components/component_page.mdx.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: {{ name }}
mode: "wide"
---

{{ description }}

<img src="/framework/public/components/{{type}}.png" />

{{ docs }}

{% if fields %}
## Fields

<table className="componentFields">
<thead>
<th>Name</th>
<th>Type</th>
<th class="desc">Description</th>
<th>Options</th>
</thead>
<tbody>
{% for _, field in fields %}
<tr>
<td>{{ field.name }}</td>
<td>{{ field.type }}</td>
<td>{{ field.desc }}</td>
<td>
<ol>
{% for _, option in field.options %}
<li>{{ option }}</li>
{% endfor %}
</ol>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}

{% if events %}
## Events
<AccordionGroup>
{% for event, eventInfo in events %}
<Accordion title="{{ event }}" icon="code">
{{ eventInfo.desc }}

```python
{{ eventInfo.stub | safe }}
```
</Accordion>
{% endfor %}
</AccordionGroup>
{% endif %}

## Low code usage

This component can be declared directly in Python, using [backend-driven UI](../backend-driven-ui).

```python
{{ low_code_usage | safe }}
```

{% if events %}
A function, in this example `handle_event`, should be implemented in your code to handle events.
```python
{{ event_handler | safe }}
```
{% endif %}


## Reference

* <a href="https://github.com/streamsync-cloud/streamsync/blob/dev/src/ui/{{fileRef}}" target="_blank" >Explore this component's source code on GitHub</a>
123 changes: 0 additions & 123 deletions docs/docs/.vitepress/config.ts

This file was deleted.

Loading

0 comments on commit 3470f2e

Please sign in to comment.