Merge branch 'develop' of github.com:Budibase/budibase into frontend-core

This commit is contained in:
Andrew Kingston 2022-02-08 08:12:37 +00:00
commit d90ccc26c7
35 changed files with 940 additions and 101 deletions

214
i18n/README.jp.md Normal file
View File

@ -0,0 +1,214 @@
<p align="center">
<a href="https://www.budibase.com">
<img alt="Budibase" src="https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg" width="60" />
</a>
</p>
<h1 align="center">
Budibase
</h1>
<h3 align="center">
使って楽しいローコードプラットフォーム
</h3>
<p align="center">
Budibaseはオープンソースのローコードプラットフォームで、生産性を向上させるツールを簡単に構築することができます。
</p>
<h3 align="center">
🤖 🎨 🚀
</h3>
<br>
<p align="center">
<img alt="Budibase design ui" src="https://res.cloudinary.com/daog6scxm/image/upload/v1633524049/ui/design-ui-wide-mobile_gdaveq.jpg">
</p>
<p align="center">
<a href="https://github.com/Budibase/budibase/releases">
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/Budibase/budibase/total">
</a>
<a href="https://github.com/Budibase/budibase/releases">
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/v/release/Budibase/budibase">
</a>
<a href="https://twitter.com/intent/follow?screen_name=budibase">
<img src="https://img.shields.io/twitter/follow/budibase?style=social" alt="Follow @budibase" />
</a>
<img src="https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg" alt="Code of conduct" />
<a href="https://codecov.io/gh/Budibase/budibase">
<img src="https://codecov.io/gh/Budibase/budibase/graph/badge.svg?token=E8W2ZFXQOH"/>
</a>
</p>
<h3 align="center">
<a href="https://docs.budibase.com/getting-started">はじめに</a>
<span> · </span>
<a href="https://docs.budibase.com">ドキュメント</a>
<span> · </span>
<a href="https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas">機能リクエスト</a>
<span> · </span>
<a href="https://github.com/Budibase/budibase/issues">バグ報告</a>
<span> · </span>
サポート: <a href="https://github.com/Budibase/budibase/discussions">ディスカッション</a>
</h3>
<br /><br />
## ✨ 特徴
### "本物"のソフトウェアを構築できます
ほかのプラットフォームとは違い、Budibaseだけでシングルページのアプリケーションを制作し完成させることができます。Budibaseで作られたアプリケーションは素晴らしいパフォーマンスを持っており、レスポンシブデザインにも対応しています。ユーザー達にいい印象を与えること間違いなしでしょう
<br /><br />
### 拡張性が高くオープンソース
Budibaseはオープンソースで、GPL v3ライセンスの下に公開されています。このことは、Budibaseが常にあなたのそばにいるという安心感を与えてくれることでしょう。そして、私たちは開発者に優しい環境を提供しているので、あなたは好きなだけにソースコードをフォークして改造、もしくは直接Budibaseにコントリビュートすることができます。
<br /><br />
### 既存のデータ、もしくは一から始める
Budibaseはいろんなツールから既存のデータを使用できます。たとえばMongoDB、CouchDB、 PostgreSQL、MySQL、Airtable、S3、DynamoDB、REST APIなど。ほかのプラットフォームにない特徴として、Budibaseはデータなしの状態でビジネスアプリケーションの構築を一から始めることができます。 [新しいデータリソースをリクエスト](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas)。
<p align="center">
<img alt="Budibase data" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970242/Out%20of%20beta%20launch/data_n1tlhf.png">
</p>
<br /><br />
### パワフルな内蔵コンポーネントでアプリケーションを設計し構築
Budibaseには、美しくデザインされた強力なコンポーネントが付属しており、それら使用しUIを簡単に構築することができます。また、CSSによるスタイリングオプションも豊富に用意されているので、よりクリエイティブな表現もも可能です。
[Request new component](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas)。
<p align="center">
<img alt="Budibase design" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970243/Out%20of%20beta%20launch/design-like-a-pro_qhlfeu.gif">
</p>
<br /><br />
### プロセスを自動化し、ほかのツールと連携し、Webhookをでつながる
定型化した作業を自動化して時間を節約しましょう。Webhookに接続、Eメールの自動送信など、すべてBudibaseに任せましょう。 こちらで簡単に [新しいオートメーションを作る](https://github.com/Budibase/automations)または[新しいオートメーションをリクエストすることができます](https://github.com/Budibase/budibase/discussions?discussions_q=category%3AIdeas)。
<p align="center">
<img alt="Budibase automations" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970486/Out%20of%20beta%20launch/automation_riro7u.png">
</p>
<br /><br />
### 使い親しんだツールとの統合
Budibaseは多くの人気ツールと統合されており、あなたのニーズに合わせたパーフェクトなアプリケーションを構築することができます。
<p align="center">
<img alt="Budibase integrations" src="https://res.cloudinary.com/daog6scxm/image/upload/v1636970242/Out%20of%20beta%20launch/integrations_kc7dqt.png">
</p>
<br /><br />
### 管理者のパラダイス
Budibaseはどんな規模のプロジェクトにも柔軟に対応できます。Budibaseを使えば、個人または組織のサーバーでセルフホスティングし、ユーザー、オンボーディング、SMTP、アプリ、グループ、テーマなどをひとまとめに管理することが可能です。また、ユーザーやグループにアプリポータルを提供し、グループ管理者にユーザー管理を委ねることも可能です。
- プロモーションビデオを視聴する: https://youtu.be/xoljVpty_Kw
<br /><br /><br />
## 🏁 始めましょう
<a href="https://docs.budibase.com/self-hosting/self-host"><img src="https://res.cloudinary.com/daog6scxm/image/upload/v1634808888/logo/deploy_npl9za.png" /></a>
Docker、KubernetesもしくはDegital Oceanを使用しセルフホスティングするか、セルフホスティングに困難がある、もしくは今すぐ開始したい場合はBudibase Cloudを使用しすぐに始めましょう。
### [Budibaseをセルフホスティングする](https://docs.budibase.com/self-hosting/self-host)
### [Budibase Cloudを使用する](https://budibase.com)
<br /><br />
## 🎓 Budibaseを学ぶ
Budibaseのドキュメント[はここです](https://docs.budibase.com)。
<br />
<br /><br />
## 💬 コミュニティ
もし何か問題がある、もしくはBudibaseコミュニティのほかのユーザーと交流したいのであれば私たちの[Github discussions](https://github.com/Budibase/budibase/discussions)までお越しください。
<br /><br /><br />
## ❗ 行動規範
Budibase は、すべての人を歓迎し、多様で、ハラスメントのない環境を提供することに尽力しています。Budibase コミュニティに参加するすべての人たちが私たちの[**行動規範**](https://github.com/Budibase/budibase/blob/HEAD/.github/CODE_OF_CONDUCT.md)を遵守していただくことお願いします。必ず読んでください。
<br />
<br /><br />
## 🙌 Budibaseにコントリビュート
バグレポートからプルリクエストの作成まで、すべての貢献は感謝、そして歓迎されております。新しい新機能の実装やAPIの変更を計画している場合は、まずIssueを作成してください。これであなたの貴重な考えは私たちにも伝わり、無駄とはなりません。
### どこから始めるか混乱していますか?
ここはコントリビュートをはじめるための最適な場所です! [First time issues project](https://github.com/Budibase/budibase/projects/22).
### リポジトリの構成
Budibaseは、lernaによってmonorepo方式で管理されています。budibase パッケージのビルドと公開はlernaによって管理されています。Budibaseを構成するパッケージは以下の通り
- [packages/builder](https://github.com/Budibase/budibase/tree/HEAD/packages/builder) - budibase builder クライアントサイドのsvelteアプリケーションのコードが含まれています。
- [packages/client](https://github.com/Budibase/budibase/tree/HEAD/packages/client) - ブラウザ上で動作するモジュールで、JSONの定義を読み取り、そこから"生きている"Webアプリケーションを作成します。
- [packages/server](https://github.com/Budibase/budibase/tree/HEAD/packages/server) - budibaseのサーバーです。この Koa アプリは、builder アプリと budibase アプリの JS を提供し、データベースとファイル システムと対話するための API を提供する役割を担っています。
詳しくは[CONTRIBUTING.md](https://github.com/Budibase/budibase/blob/HEAD/.github/CONTRIBUTING.md)をご覧ください。
<br /><br />
## 📝 ライセンス
Budibase はオープンソースであり、[GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html)ライセンスの下に公開されています。クライアントとコンポーネントライブラリは [MPL](https://directory.fsf.org/wiki/License:MPL-2.0)で公開されています - ですから、あなたが制作したアプリケーションはどのようなライセンスでも公開することができます。
<br /><br />
## ⭐ スター数の履歴
[![Stargazers over time](https://starchart.cc/Budibase/budibase.svg)](https://starchart.cc/Budibase/budibase)
ビルダーのアップデートの間に問題が発生する場合は[ここ](https://github.com/Budibase/budibase/blob/HEAD/.github/CONTRIBUTING.md#troubleshooting)を参考に環境をクリアにしてください。
<br /><br />
## Contributors ✨
すばらしい皆さまに感謝しかありません。([emoji key](https://allcontributors.org/docs/en/emoji-key)):
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tr>
<td align="center"><a href="http://martinmck.com"><img src="https://avatars1.githubusercontent.com/u/11256663?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Martin McKeaveney</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=shogunpurple" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=shogunpurple" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=shogunpurple" title="Tests">⚠️</a> <a href="#infra-shogunpurple" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center"><a href="http://www.michaeldrury.co.uk/"><img src="https://avatars2.githubusercontent.com/u/4407001?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Drury</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=mike12345567" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=mike12345567" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=mike12345567" title="Tests">⚠️</a> <a href="#infra-mike12345567" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a></td>
<td align="center"><a href="https://github.com/aptkingston"><img src="https://avatars3.githubusercontent.com/u/9075550?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andrew Kingston</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=aptkingston" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=aptkingston" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=aptkingston" title="Tests">⚠️</a> <a href="#design-aptkingston" title="Design">🎨</a></td>
<td align="center"><a href="https://budibase.com/"><img src="https://avatars3.githubusercontent.com/u/3524181?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Michael Shanks</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=mjashanks" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=mjashanks" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=mjashanks" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/kevmodrome"><img src="https://avatars3.githubusercontent.com/u/534488?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Kevin Åberg Kultalahti</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=kevmodrome" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=kevmodrome" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=kevmodrome" title="Tests">⚠️</a></td>
<td align="center"><a href="https://www.budibase.com/"><img src="https://avatars2.githubusercontent.com/u/49767913?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joe</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=joebudi" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=joebudi" title="Code">💻</a> <a href="#content-joebudi" title="Content">🖋</a> <a href="#design-joebudi" title="Design">🎨</a></td>
<td align="center"><a href="https://github.com/Rory-Powell"><img src="https://avatars.githubusercontent.com/u/8755148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Rory Powell</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=Rory-Powell" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=Rory-Powell" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=Rory-Powell" title="Tests">⚠️</a></td>
</tr>
<tr>
<td align="center"><a href="https://github.com/PClmnt"><img src="https://avatars.githubusercontent.com/u/5665926?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Peter Clement</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=PClmnt" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=PClmnt" title="Documentation">📖</a> <a href="https://github.com/Budibase/budibase/commits?author=PClmnt" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/Conor-Mack"><img src="https://avatars1.githubusercontent.com/u/36074859?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Conor_Mack</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=Conor-Mack" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=Conor-Mack" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/pngwn"><img src="https://avatars1.githubusercontent.com/u/12937446?v=4?s=100" width="100px;" alt=""/><br /><sub><b>pngwn</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=pngwn" title="Code">💻</a> <a href="https://github.com/Budibase/budibase/commits?author=pngwn" title="Tests">⚠️</a></td>
<td align="center"><a href="https://github.com/HugoLd"><img src="https://avatars0.githubusercontent.com/u/26521848?v=4?s=100" width="100px;" alt=""/><br /><sub><b>HugoLd</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=HugoLd" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/victoriasloan"><img src="https://avatars.githubusercontent.com/u/9913651?v=4?s=100" width="100px;" alt=""/><br /><sub><b>victoriasloan</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=victoriasloan" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/yashank09"><img src="https://avatars.githubusercontent.com/u/37672190?v=4?s=100" width="100px;" alt=""/><br /><sub><b>yashank09</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=yashank09" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/SOVLOOKUP"><img src="https://avatars.githubusercontent.com/u/53158137?v=4?s=100" width="100px;" alt=""/><br /><sub><b>SOVLOOKUP</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=SOVLOOKUP" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/seoulaja"><img src="https://avatars.githubusercontent.com/u/15101654?v=4?s=100" width="100px;" alt=""/><br /><sub><b>seoulaja</b></sub></a><br /><a href="#translation-seoulaja" title="Translation">🌍</a></td>
<td align="center"><a href="https://github.com/mslourens"><img src="https://avatars.githubusercontent.com/u/1907152?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maurits Lourens</b></sub></a><br /><a href="https://github.com/Budibase/budibase/commits?author=mslourens" title="Tests">⚠️</a> <a href="https://github.com/Budibase/budibase/commits?author=mslourens" title="Code">💻</a></td>
</tr>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
このプロジェクトは、[all-contributors](https://github.com/all-contributors/all-contributors)仕様に準拠しています。どのような貢献でも歓迎します。

View File

@ -1,5 +1,5 @@
{ {
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/backend-core", "name": "@budibase/backend-core",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"description": "Budibase backend core libraries used in server and worker", "description": "Budibase backend core libraries used in server and worker",
"main": "src/index.js", "main": "src/index.js",
"author": "Budibase", "author": "Budibase",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/bbui", "name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.", "description": "A UI solution used in the different Budibase projects.",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"module": "dist/bbui.es.js", "module": "dist/bbui.es.js",
@ -79,6 +79,7 @@
"@spectrum-css/underlay": "^2.0.9", "@spectrum-css/underlay": "^2.0.9",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",
"dayjs": "^1.10.4", "dayjs": "^1.10.4",
"easymde": "^2.16.1",
"svelte-flatpickr": "^3.2.3", "svelte-flatpickr": "^3.2.3",
"svelte-portal": "^1.0.0" "svelte-portal": "^1.0.0"
}, },

View File

@ -0,0 +1,42 @@
<script>
import MarkdownEditor from "../../Markdown/MarkdownEditor.svelte"
export let value = ""
export let placeholder = null
export let disabled = false
export let error = null
export let height = null
export let id = null
export let fullScreenOffset = null
export let easyMDEOptions = null
</script>
<div class:error>
<MarkdownEditor
{value}
{placeholder}
{height}
{id}
{fullScreenOffset}
{disabled}
{easyMDEOptions}
on:change
/>
</div>
<style>
.error :global(.EasyMDEContainer .editor-toolbar) {
border-top-color: var(--spectrum-semantic-negative-color-default);
border-left-color: var(--spectrum-semantic-negative-color-default);
border-right-color: var(--spectrum-semantic-negative-color-default);
}
.error :global(.EasyMDEContainer .CodeMirror) {
border-bottom-color: var(--spectrum-semantic-negative-color-default);
border-left-color: var(--spectrum-semantic-negative-color-default);
border-right-color: var(--spectrum-semantic-negative-color-default);
}
.error :global(.EasyMDEContainer .editor-preview-side) {
border-bottom-color: var(--spectrum-semantic-negative-color-default);
border-right-color: var(--spectrum-semantic-negative-color-default);
}
</style>

View File

@ -22,11 +22,23 @@
dispatch("change", event.target.value) dispatch("change", event.target.value)
focus = false focus = false
} }
const getStyleString = (attribute, value) => {
if (!attribute || value == null) {
return ""
}
if (isNaN(value)) {
return `${attribute}:${value};`
}
return `${attribute}:${value}px;`
}
$: heightString = getStyleString("height", height)
$: minHeightString = getStyleString("min-height", minHeight)
</script> </script>
<div <div
style={(height ? `height: ${height}px;` : "") + style={`${heightString}${minHeightString}`}
(minHeight ? `min-height: ${minHeight}px` : "")}
class="spectrum-Textfield spectrum-Textfield--multiline" class="spectrum-Textfield spectrum-Textfield--multiline"
class:is-invalid={!!error} class:is-invalid={!!error}
class:is-disabled={disabled} class:is-disabled={disabled}

View File

@ -10,3 +10,4 @@ export { default as CoreSearch } from "./Search.svelte"
export { default as CoreDatePicker } from "./DatePicker.svelte" export { default as CoreDatePicker } from "./DatePicker.svelte"
export { default as CoreDropzone } from "./Dropzone.svelte" export { default as CoreDropzone } from "./Dropzone.svelte"
export { default as CoreStepper } from "./Stepper.svelte" export { default as CoreStepper } from "./Stepper.svelte"
export { default as CoreRichTextField } from "./RichTextField.svelte"

View File

@ -0,0 +1,36 @@
<script>
import Field from "./Field.svelte"
import RichTextField from "./Core/RichTextField.svelte"
import { createEventDispatcher } from "svelte"
export let value = null
export let label = null
export let labelPosition = "above"
export let placeholder = null
export let disabled = false
export let error = null
export let height = null
export let id = null
export let fullScreenOffset = null
export let easyMDEOptions = null
const dispatch = createEventDispatcher()
const onChange = e => {
value = e.detail
dispatch("change", e.detail)
}
</script>
<Field {label} {labelPosition} {error}>
<RichTextField
{error}
{disabled}
{value}
{placeholder}
{height}
{id}
{fullScreenOffset}
{easyMDEOptions}
on:change={onChange}
/>
</Field>

View File

@ -0,0 +1,60 @@
<script>
import SpectrumMDE from "./SpectrumMDE.svelte"
import { createEventDispatcher } from "svelte"
export let value = null
export let height = null
export let placeholder = null
export let id = null
export let fullScreenOffset = 0
export let disabled = false
export let easyMDEOptions
const dispatch = createEventDispatcher()
let latestValue
let mde
// Ensure the value is updated if the value prop changes outside the editor's
// control
$: checkValue(value)
$: mde?.codemirror.on("change", debouncedUpdate)
const checkValue = val => {
if (mde && val !== latestValue) {
mde.value(val)
}
}
const debounce = (fn, interval) => {
let timeout
return () => {
clearTimeout(timeout)
timeout = setTimeout(fn, interval)
}
}
const update = () => {
latestValue = mde.value()
dispatch("change", latestValue)
}
// Debounce the update function to avoid spamming it constantly
const debouncedUpdate = debounce(update, 250)
</script>
{#key height}
<SpectrumMDE
bind:mde
scroll={true}
{height}
{id}
{fullScreenOffset}
{disabled}
easyMDEOptions={{
initialValue: value,
placeholder,
...easyMDEOptions,
}}
/>
{/key}

View File

@ -0,0 +1,70 @@
<script>
import SpectrumMDE from "./SpectrumMDE.svelte"
export let value
export let height
let mde
// Keep the value up to date
$: mde && mde.value(value || "")
$: {
if (mde && !mde.isPreviewActive()) {
mde.togglePreview()
}
}
</script>
<div class="markdown-viewer" style="height:{height};">
<SpectrumMDE
bind:mde
scroll={false}
easyMDEOptions={{
initialValue: value,
toolbar: false,
}}
/>
</div>
<style>
.markdown-viewer {
overflow: auto;
}
/* Remove padding, borders and background colors */
.markdown-viewer :global(.editor-preview) {
padding: 0;
border: none;
background: transparent;
}
.markdown-viewer :global(.CodeMirror) {
border: none;
background: transparent;
padding: 0;
}
.markdown-viewer :global(.EasyMDEContainer) {
background: transparent;
}
/* Hide the actual code editor */
.markdown-viewer :global(.CodeMirror-scroll) {
display: none;
}
/*Hide the scrollbar*/
.markdown-viewer :global(.CodeMirror-vscrollbar) {
display: none !important;
}
/*Position relatively so we only consume whatever space we need */
.markdown-viewer :global(.editor-preview-full) {
position: relative;
}
/* Remove margin on the first and last components to fully trim the preview */
.markdown-viewer :global(.editor-preview-full > :first-child) {
margin-top: 0;
}
.markdown-viewer :global(.editor-preview-full > :last-child) {
margin-bottom: 0;
}
/* Code blocks in preview */
.markdown-viewer :global(.editor-preview-full pre) {
background: var(--spectrum-global-color-gray-200);
}
</style>

View File

@ -0,0 +1,184 @@
<script>
import EasyMDE from "easymde"
import "easymde/dist/easymde.min.css"
import { onMount } from "svelte"
export let height = null
export let scroll = true
export let easyMDEOptions = null
export let mde = null
export let id = null
export let fullScreenOffset = null
export let disabled = false
let element
onMount(() => {
height = height || "200px"
mde = new EasyMDE({
element,
spellChecker: false,
status: false,
unorderedListStyle: "-",
maxHeight: scroll ? height : undefined,
minHeight: scroll ? undefined : height,
...easyMDEOptions,
})
// Revert the editor when we unmount
return () => {
mde.toTextArea()
}
})
$: styleString = getStyleString(fullScreenOffset)
const getStyleString = offset => {
let string = ""
string += `--fullscreen-offset-x:${offset?.x || "0px"};`
string += `--fullscreen-offset-y:${offset?.y || "0px"};`
return string
}
</script>
<div class:disabled style={styleString}>
<textarea disabled {id} bind:this={element} />
</div>
<style>
/* Disabled styles */
.disabled :global(textarea) {
display: none;
}
.disabled :global(.CodeMirror-cursor) {
display: none;
}
.disabled :global(.EasyMDEContainer) {
pointer-events: none;
}
.disabled :global(.editor-toolbar button i) {
color: var(--spectrum-global-color-gray-400);
}
.disabled :global(.CodeMirror) {
color: var(--spectrum-global-color-gray-600);
}
/* Toolbar container */
:global(.EasyMDEContainer .editor-toolbar) {
background: var(--spectrum-global-color-gray-50);
border-top: 1px solid var(--spectrum-alias-border-color);
border-left: 1px solid var(--spectrum-alias-border-color);
border-right: 1px solid var(--spectrum-alias-border-color);
}
/* Main code mirror instance and default color */
:global(.EasyMDEContainer .CodeMirror) {
border: 1px solid var(--spectrum-alias-border-color);
background: var(--spectrum-global-color-gray-50);
color: var(--spectrum-alias-text-color);
}
/* Toolbar button active state */
:global(.EasyMDEContainer .editor-toolbar button.active) {
background: var(--spectrum-global-color-gray-200);
border-color: var(--spectrum-global-color-gray-400);
}
/* Toolbar button hover state */
:global(.EasyMDEContainer .editor-toolbar button:hover) {
background: var(--spectrum-global-color-gray-200);
border-color: var(--spectrum-global-color-gray-400);
}
/* Toolbar button color */
:global(.EasyMDEContainer .editor-toolbar button i) {
color: var(--spectrum-global-color-gray-800);
}
/* Separator between toolbar buttons*/
:global(.EasyMDEContainer .editor-toolbar i.separator) {
border-color: var(--spectrum-global-color-gray-300);
}
/* Cursor */
:global(.EasyMDEContainer .CodeMirror-cursor) {
border-color: var(--spectrum-alias-text-color);
}
/* Text selections */
:global(.EasyMDEContainer .CodeMirror-selectedtext) {
background: var(--spectrum-global-color-gray-400) !important;
}
/* Background of lines containing selected text */
:global(.EasyMDEContainer .CodeMirror-selected) {
background: var(--spectrum-global-color-gray-400) !important;
}
/* Color of text for images and links */
:global(.EasyMDEContainer .cm-s-easymde .cm-link) {
color: var(--spectrum-global-color-gray-600);
}
/* Color of URL for images and links */
:global(.EasyMDEContainer .cm-s-easymde .cm-url) {
color: var(--spectrum-global-color-gray-500);
}
/* Full preview window */
:global(.EasyMDEContainer .editor-preview) {
background: var(--spectrum-global-color-gray-50);
}
/* Side by side preview window */
:global(.EasyMDEContainer .editor-preview) {
border: 1px solid var(--spectrum-alias-border-color);
}
/* Code blocks in editor */
:global(.EasyMDEContainer .cm-s-easymde .cm-comment) {
background: var(--spectrum-global-color-gray-100);
}
/* Code blocks in preview */
:global(.EasyMDEContainer pre) {
background: var(--spectrum-global-color-gray-100);
padding: 4px;
border-radius: 4px;
}
:global(.EasyMDEContainer code) {
color: #e83e8c;
}
:global(.EasyMDEContainer pre code) {
color: var(--spectrum-alias-text-color);
}
/* Block quotes */
:global(.EasyMDEContainer blockquote) {
border-left: 4px solid var(--spectrum-global-color-gray-400);
color: var(--spectrum-global-color-gray-700);
margin-left: 0;
padding-left: 20px;
}
/* HR's */
:global(.EasyMDEContainer hr) {
background-color: var(--spectrum-global-color-gray-300);
border: none;
height: 2px;
}
/* Tables */
:global(.EasyMDEContainer td, .EasyMDEContainer th) {
border-color: var(--spectrum-alias-border-color) !important;
}
/* Links */
:global(.EasyMDEContainer a) {
color: var(--primaryColor);
}
:global(.EasyMDEContainer a:hover) {
color: var(--primaryColorHover);
}
/* Allow full screen offset */
:global(.EasyMDEContainer .editor-toolbar.fullscreen) {
left: var(--fullscreen-offset-x);
top: var(--fullscreen-offset-y);
}
:global(.EasyMDEContainer .CodeMirror-fullscreen) {
left: var(--fullscreen-offset-x);
top: calc(50px + var(--fullscreen-offset-y));
}
:global(.EasyMDEContainer .CodeMirror-fullscreen.CodeMirror-sided) {
width: calc((100% - var(--fullscreen-offset-x)) / 2) !important;
}
:global(.EasyMDEContainer .editor-preview-side) {
left: calc(50% + (var(--fullscreen-offset-x) / 2));
top: calc(50px + var(--fullscreen-offset-y));
width: calc((100% - var(--fullscreen-offset-x)) / 2) !important;
}
</style>

View File

@ -1,7 +1,12 @@
<script> <script>
import { createEventDispatcher } from "svelte"
export let type = "info" export let type = "info"
export let icon = "Info" export let icon = "Info"
export let message = "" export let message = ""
export let dismissable = false
const dispatch = createEventDispatcher()
</script> </script>
<div class="spectrum-Toast spectrum-Toast--{type}"> <div class="spectrum-Toast spectrum-Toast--{type}">
@ -17,4 +22,28 @@
<div class="spectrum-Toast-body"> <div class="spectrum-Toast-body">
<div class="spectrum-Toast-content">{message || ""}</div> <div class="spectrum-Toast-content">{message || ""}</div>
</div> </div>
{#if dismissable}
<div class="spectrum-Toast-buttons">
<button
class="spectrum-ClearButton spectrum-ClearButton--overBackground spectrum-ClearButton--sizeM"
on:click={() => dispatch("dismiss")}
>
<div class="spectrum-ClearButton-fill">
<svg
class="spectrum-ClearButton-icon spectrum-Icon spectrum-UIIcon-Cross100"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Cross100" />
</svg>
</div>
</button>
</div>
{/if}
</div> </div>
<style>
.spectrum-Toast {
pointer-events: all;
}
</style>

View File

@ -1,7 +1,6 @@
<script> <script>
import "@spectrum-css/toast/dist/index-vars.css" import "@spectrum-css/toast/dist/index-vars.css"
import Portal from "svelte-portal" import Portal from "svelte-portal"
import { flip } from "svelte/animate"
import { notifications } from "../Stores/notifications" import { notifications } from "../Stores/notifications"
import Notification from "./Notification.svelte" import Notification from "./Notification.svelte"
import { fly } from "svelte/transition" import { fly } from "svelte/transition"
@ -9,9 +8,15 @@
<Portal target=".modal-container"> <Portal target=".modal-container">
<div class="notifications"> <div class="notifications">
{#each $notifications as { type, icon, message, id } (id)} {#each $notifications as { type, icon, message, id, dismissable } (id)}
<div animate:flip transition:fly={{ y: -30 }}> <div transition:fly={{ y: -30 }}>
<Notification {type} {icon} {message} /> <Notification
{type}
{icon}
{message}
{dismissable}
on:dismiss={() => notifications.dismiss(id)}
/>
</div> </div>
{/each} {/each}
</div> </div>

View File

@ -20,20 +20,29 @@ export const createNotificationStore = () => {
setTimeout(() => (block = false), timeout) setTimeout(() => (block = false), timeout)
} }
const send = (message, type = "default", icon = "") => { const send = (message, type = "default", icon = "", autoDismiss = true) => {
if (block) { if (block) {
return return
} }
let _id = id() let _id = id()
_notifications.update(state => { _notifications.update(state => {
return [...state, { id: _id, type, message, icon }] return [
...state,
{ id: _id, type, message, icon, dismissable: !autoDismiss },
]
})
if (autoDismiss) {
const timeoutId = setTimeout(() => {
dismissNotification(_id)
}, NOTIFICATION_TIMEOUT)
timeoutIds.add(timeoutId)
}
}
const dismissNotification = id => {
_notifications.update(state => {
return state.filter(n => n.id !== id)
}) })
const timeoutId = setTimeout(() => {
_notifications.update(state => {
return state.filter(({ id }) => id !== _id)
})
}, NOTIFICATION_TIMEOUT)
timeoutIds.add(timeoutId)
} }
const { subscribe } = _notifications const { subscribe } = _notifications
@ -42,10 +51,11 @@ export const createNotificationStore = () => {
subscribe, subscribe,
send, send,
info: msg => send(msg, "info", "Info"), info: msg => send(msg, "info", "Info"),
error: msg => send(msg, "error", "Alert"), error: msg => send(msg, "error", "Alert", false),
warning: msg => send(msg, "warning", "Alert"), warning: msg => send(msg, "warning", "Alert"),
success: msg => send(msg, "success", "CheckmarkCircle"), success: msg => send(msg, "success", "CheckmarkCircle"),
blockNotifications, blockNotifications,
dismiss: dismissNotification,
} }
} }

View File

@ -60,6 +60,9 @@ export { default as StatusLight } from "./StatusLight/StatusLight.svelte"
export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte" export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte" export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte"
export { default as Banner } from "./Banner/Banner.svelte" export { default as Banner } from "./Banner/Banner.svelte"
export { default as MarkdownEditor } from "./Markdown/MarkdownEditor.svelte"
export { default as MarkdownViewer } from "./Markdown/MarkdownViewer.svelte"
export { default as RichTextField } from "./Form/RichTextField.svelte"
// Renderers // Renderers
export { default as BoldRenderer } from "./Table/BoldRenderer.svelte" export { default as BoldRenderer } from "./Table/BoldRenderer.svelte"

View File

@ -271,6 +271,13 @@
resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.2.tgz#ea9062c3c98dfc6ba59e5df14a03025ad8969999" resolved "https://registry.yarnpkg.com/@spectrum-css/vars/-/vars-3.0.2.tgz#ea9062c3c98dfc6ba59e5df14a03025ad8969999"
integrity sha512-vzS9KqYXot4J3AEER/u618MXWAS+IoMvYMNrOoscKiLLKYQWenaueakUWulFonToPd/9vIpqtdbwxznqrK5qDw== integrity sha512-vzS9KqYXot4J3AEER/u618MXWAS+IoMvYMNrOoscKiLLKYQWenaueakUWulFonToPd/9vIpqtdbwxznqrK5qDw==
"@types/codemirror@^5.60.4":
version "5.60.5"
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-5.60.5.tgz#5b989a3b4bbe657458cf372c92b6bfda6061a2b7"
integrity sha512-TiECZmm8St5YxjFUp64LK0c8WU5bxMDt9YaAek1UqUb9swrSCoJhh92fWu1p3mTEqlHjhB5sY7OFBhWroJXZVg==
dependencies:
"@types/tern" "*"
"@types/estree@*": "@types/estree@*":
version "0.0.47" version "0.0.47"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.47.tgz#d7a51db20f0650efec24cd04994f523d93172ed4"
@ -281,6 +288,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
"@types/marked@^4.0.1":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/marked/-/marked-4.0.2.tgz#cb2dbf10da2f41cf20bd91fb5f89b67540c282f7"
integrity sha512-auNrZ/c0w6wsM9DccwVxWHssrMDezHUAXNesdp2RQrCVCyrQbOiSq7yqdJKrUQQpw9VTm7CGYJH2A/YG7jjrjQ==
"@types/node@*": "@types/node@*":
version "14.14.41" version "14.14.41"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615"
@ -303,6 +315,13 @@
dependencies: dependencies:
"@types/node" "*" "@types/node" "*"
"@types/tern@*":
version "0.23.4"
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.4.tgz#03926eb13dbeaf3ae0d390caf706b2643a0127fb"
integrity sha512-JAUw1iXGO1qaWwEOzxTKJZ/5JxVeON9kvGZ/osgZaJImBnyjyn0cjovPsf6FNLmyGY8Vw9DoXZCMlfMkMwHRWg==
dependencies:
"@types/estree" "*"
accepts@~1.3.7: accepts@~1.3.7:
version "1.3.7" version "1.3.7"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
@ -525,6 +544,18 @@ coa@^2.0.2:
chalk "^2.4.1" chalk "^2.4.1"
q "^1.1.2" q "^1.1.2"
codemirror-spell-checker@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz#1c660f9089483ccb5113b9ba9ca19c3f4993371e"
integrity sha1-HGYPkIlIPMtRE7m6nKGcP0mTNx4=
dependencies:
typo-js "*"
codemirror@^5.63.1:
version "5.65.1"
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.65.1.tgz#5988a812c974c467f964bcc1a00c944e373de502"
integrity sha512-s6aac+DD+4O2u1aBmdxhB7yz2XU7tG3snOyQ05Kxifahz7hoxnfxIRHxiCSEv3TUC38dIVH8G+lZH9UWSfGQxA==
color-convert@^1.9.0, color-convert@^1.9.1: color-convert@^1.9.0, color-convert@^1.9.1:
version "1.9.3" version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@ -861,6 +892,17 @@ dot-prop@^5.2.0:
dependencies: dependencies:
is-obj "^2.0.0" is-obj "^2.0.0"
easymde@^2.16.1:
version "2.16.1"
resolved "https://registry.yarnpkg.com/easymde/-/easymde-2.16.1.tgz#f4c2380312615cb33826f1a1fecfaa4022ff551a"
integrity sha512-FihYgjRsKfhGNk89SHSqxKLC4aJ1kfybPWW6iAmtb5GnXu+tnFPSzSaGBmk1RRlCuhFSjhF0SnIMGVPjEzkr6g==
dependencies:
"@types/codemirror" "^5.60.4"
"@types/marked" "^4.0.1"
codemirror "^5.63.1"
codemirror-spell-checker "1.1.2"
marked "^4.0.10"
ee-first@1.1.1: ee-first@1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -1472,6 +1514,11 @@ magic-string@^0.25.7:
dependencies: dependencies:
sourcemap-codec "^1.4.4" sourcemap-codec "^1.4.4"
marked@^4.0.10:
version "4.0.12"
resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
mdn-data@2.0.14: mdn-data@2.0.14:
version "2.0.14" version "2.0.14"
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
@ -2490,6 +2537,11 @@ type-is@~1.6.17, type-is@~1.6.18:
media-typer "0.3.0" media-typer "0.3.0"
mime-types "~2.1.24" mime-types "~2.1.24"
typo-js@*:
version "1.2.1"
resolved "https://registry.yarnpkg.com/typo-js/-/typo-js-1.2.1.tgz#334a0d8c3f6c56f2f1e15fdf6c31677793cbbe9b"
integrity sha512-bTGLjbD3WqZDR3CgEFkyi9Q/SS2oM29ipXrWfDb4M74ea69QwKAECVceYpaBu0GfdnASMg9Qfl67ttB23nePHg==
unbox-primitive@^1.0.0: unbox-primitive@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -64,10 +64,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.49-alpha.14", "@budibase/bbui": "^1.0.50-alpha.0",
"@budibase/client": "^1.0.49-alpha.14", "@budibase/client": "^1.0.50-alpha.0",
"@budibase/frontend-core": "^1.0.49-alpha.14", "@budibase/frontend-core": "^1.0.50-alpha.0",
"@budibase/string-templates": "^1.0.49-alpha.14", "@budibase/string-templates": "^1.0.50-alpha.0",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View File

@ -169,6 +169,11 @@ export function makeDatasourceFormComponents(datasource) {
optionsSource: "schema", optionsSource: "schema",
}) })
} }
if (fieldType === "longform") {
component.customProps({
format: "auto",
})
}
if (fieldType === "array") { if (fieldType === "array") {
component.customProps({ component.customProps({
placeholder: "Choose an option", placeholder: "Choose an option",

View File

@ -4,9 +4,10 @@
Select, Select,
DatePicker, DatePicker,
Toggle, Toggle,
TextArea,
Multiselect, Multiselect,
Label, Label,
RichTextField,
TextArea,
} from "@budibase/bbui" } from "@budibase/bbui"
import Dropzone from "components/common/Dropzone.svelte" import Dropzone from "components/common/Dropzone.svelte"
import { capitalise } from "helpers" import { capitalise } from "helpers"
@ -43,7 +44,11 @@
{:else if type === "link"} {:else if type === "link"}
<LinkedRowSelector bind:linkedRows={value} schema={meta} /> <LinkedRowSelector bind:linkedRows={value} schema={meta} />
{:else if type === "longform"} {:else if type === "longform"}
<TextArea {label} bind:value /> {#if meta.useRichText}
<RichTextField {label} height="150px" bind:value />
{:else}
<TextArea {label} height="150px" bind:value />
{/if}
{:else if type === "json"} {:else if type === "json"}
<Label>{label}</Label> <Label>{label}</Label>
<Editor <Editor

View File

@ -371,7 +371,7 @@
{#if canBeSearched && !external} {#if canBeSearched && !external}
<div> <div>
<Label grey small>Search Indexes</Label> <Label>Search Indexes</Label>
<Toggle <Toggle
value={indexes[0] === field.name} value={indexes[0] === field.name}
disabled={indexes[1] === field.name} disabled={indexes[1] === field.name}
@ -398,6 +398,19 @@
label="Options (one per line)" label="Options (one per line)"
bind:values={field.constraints.inclusion} bind:values={field.constraints.inclusion}
/> />
{:else if field.type === "longform"}
<div>
<Label
size="M"
tooltip="Rich text includes support for images, links, tables, lists and more"
>
Formatting
</Label>
<Toggle
bind:value={field.useRichText}
text="Enable rich text support (markdown)"
/>
</div>
{:else if field.type === "array"} {:else if field.type === "array"}
<ValuesList <ValuesList
label="Options (one per line)" label="Options (one per line)"

View File

@ -81,7 +81,8 @@
"backgroundimage", "backgroundimage",
"link", "link",
"icon", "icon",
"embed" "embed",
"markdownviewer"
] ]
} }
] ]

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {

View File

@ -2365,11 +2365,10 @@
] ]
}, },
"longformfield": { "longformfield": {
"name": "Rich Text", "name": "Long Form Field",
"icon": "TextParagraph", "icon": "TextParagraph",
"styles": ["size"], "styles": ["size"],
"editable": true, "editable": true,
"illegalChildren": ["section"],
"settings": [ "settings": [
{ {
"type": "field/longform", "type": "field/longform",
@ -2392,6 +2391,27 @@
"label": "Default value", "label": "Default value",
"key": "defaultValue" "key": "defaultValue"
}, },
{
"type": "select",
"label": "Formatting",
"key": "format",
"placeholder": null,
"options": [
{
"label": "Auto",
"value": "auto"
},
{
"label": "Plain text",
"value": "plain"
},
{
"label": "Rich text (markdown)",
"value": "rich"
}
],
"defaultValue": "auto"
},
{ {
"type": "boolean", "type": "boolean",
"label": "Disabled", "label": "Disabled",
@ -2402,35 +2422,6 @@
"type": "validation/string", "type": "validation/string",
"label": "Validation", "label": "Validation",
"key": "validation" "key": "validation"
},
{
"type": "select",
"label": "Alignment",
"key": "align",
"defaultValue": "left",
"showInBar": true,
"barStyle": "buttons",
"options": [{
"label": "Left",
"value": "left",
"barIcon": "TextAlignLeft",
"barTitle": "Align left"
}, {
"label": "Center",
"value": "center",
"barIcon": "TextAlignCenter",
"barTitle": "Align center"
}, {
"label": "Right",
"value": "right",
"barIcon": "TextAlignRight",
"barTitle": "Align right"
}, {
"label": "Justify",
"value": "justify",
"barIcon": "TextAlignJustify",
"barTitle": "Justify text"
}]
} }
] ]
}, },
@ -3448,5 +3439,18 @@
"key": "validation" "key": "validation"
} }
] ]
},
"markdownviewer": {
"name": "Markdown Viewer",
"icon": "TaskList",
"styles": ["size"],
"editable": true,
"settings": [
{
"type": "text",
"label": "Markdown",
"key": "value"
}
]
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"license": "MPL-2.0", "license": "MPL-2.0",
"module": "dist/budibase-client.js", "module": "dist/budibase-client.js",
"main": "dist/budibase-client.js", "main": "dist/budibase-client.js",
@ -19,9 +19,9 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.49-alpha.14", "@budibase/bbui": "^1.0.50-alpha.0",
"@budibase/frontend-core": "^1.0.49-alpha.14", "@budibase/frontend-core": "^1.0.50-alpha.0",
"@budibase/string-templates": "^1.0.49-alpha.14", "@budibase/string-templates": "^1.0.50-alpha.0",
"regexparam": "^1.3.0", "regexparam": "^1.3.0",
"rollup-plugin-polyfill-node": "^0.8.0", "rollup-plugin-polyfill-node": "^0.8.0",
"shortid": "^2.2.15", "shortid": "^2.2.15",

View File

@ -1,5 +1,6 @@
<script> <script>
import { getContext } from "svelte" import { getContext, setContext } from "svelte"
import { writable } from "svelte/store"
import { Heading, Icon } from "@budibase/bbui" import { Heading, Icon } from "@budibase/bbui"
import { FieldTypes } from "../../constants" import { FieldTypes } from "../../constants"
import active from "svelte-spa-router/active" import active from "svelte-spa-router/active"
@ -29,6 +30,16 @@
Small: "s", Small: "s",
} }
// Set some layout context. This isn't used in bindings but can be used
// determine things about the current app layout.
$: mobile = $context.device.mobile
const store = writable({ headerHeight: 0 })
$: store.set({
screenXOffset: getScreenXOffset(navigation, mobile),
screenYOffset: getScreenYOffset(navigation, mobile),
})
setContext("layout", store)
// Permanently go into peek mode if we ever get the peek flag // Permanently go into peek mode if we ever get the peek flag
let isPeeking = false let isPeeking = false
$: { $: {
@ -58,13 +69,27 @@
if ($builderStore.inBuilder) return if ($builderStore.inBuilder) return
window.location.href = "/builder/apps" window.location.href = "/builder/apps"
} }
const getScreenXOffset = (navigation, mobile) => {
if (navigation !== "Left") {
return 0
}
return mobile ? "0px" : "250px"
}
const getScreenYOffset = (navigation, mobile) => {
if (mobile) {
return !navigation || navigation === "None" ? 0 : "61px"
} else {
return navigation === "Top" ? "137px" : "0px"
}
}
</script> </script>
<div <div
class="layout layout--{typeClass}" class="layout layout--{typeClass}"
use:styleable={$component.styles} use:styleable={$component.styles}
class:desktop={!$context.device.mobile} class:desktop={!mobile}
class:mobile={!!$context.device.mobile} class:mobile={!!mobile}
> >
{#if typeClass !== "none"} {#if typeClass !== "none"}
<div <div

View File

@ -0,0 +1,19 @@
<script>
import { MarkdownViewer } from "@budibase/bbui"
import { getContext } from "svelte"
import Placeholder from "./Placeholder.svelte"
export let value
const component = getContext("component")
const { builderStore, styleable } = getContext("sdk")
const height = $component.styles?.normal?.height
</script>
<div use:styleable={$component.styles}>
{#if value}
<MarkdownViewer {value} {height} />
{:else if $builderStore.inBuilder}
<Placeholder />
{/if}
</div>

View File

@ -1,7 +1,8 @@
<script> <script>
import { CoreTextArea } from "@budibase/bbui" import { getContext, setContext } from "svelte"
import { writable } from "svelte/store"
import { CoreRichTextField, CoreTextArea } from "@budibase/bbui"
import Field from "./Field.svelte" import Field from "./Field.svelte"
import { getContext } from "svelte"
export let field export let field
export let label export let label
@ -9,13 +10,40 @@
export let disabled = false export let disabled = false
export let validation export let validation
export let defaultValue = "" export let defaultValue = ""
export let align export let format = "auto"
let fieldState let fieldState
let fieldApi let fieldApi
let fieldSchema
const context = getContext("context")
const component = getContext("component") const component = getContext("component")
$: height = $component.styles?.normal?.height || "124px" const layout = getContext("layout")
const newContext = writable($component)
setContext("component", newContext)
// Determine whether we should use a rich or plain text component.
// We treat undefined as "auto".
$: useRichText =
format === "rich" || (format !== "plain" && fieldSchema?.useRichText)
// Extract the settings height so we can pass it on to the rich text field.
// We then wipe the height style so that the field will automatically size
// itself based on the height of the rich text field.
let height
$: {
height = $component.styles?.normal?.height || "150px"
newContext.set({
...$component,
styles: {
...$component.styles,
normal: {
...$component.styles.normal,
height: undefined,
},
},
})
}
</script> </script>
<Field <Field
@ -27,29 +55,36 @@
type="longform" type="longform"
bind:fieldState bind:fieldState
bind:fieldApi bind:fieldApi
bind:fieldSchema
> >
{#if fieldState} {#if fieldState}
<div style="--height: {height};"> {#if useRichText}
<CoreRichTextField
value={fieldState.value}
on:change={e => fieldApi.setValue(e.detail)}
disabled={fieldState.disabled}
error={fieldState.error}
id={fieldState.fieldId}
{placeholder}
{height}
fullScreenOffset={{
x: $layout.screenXOffset,
y: $layout.screenYOffset,
}}
easyMDEOptions={{
hideIcons: $context.device.mobile ? ["side-by-side", "guide"] : [],
}}
/>
{:else}
<CoreTextArea <CoreTextArea
value={fieldState.value} value={fieldState.value}
on:change={e => fieldApi.setValue(e.detail)} on:change={e => fieldApi.setValue(e.detail)}
disabled={fieldState.disabled} disabled={fieldState.disabled}
error={fieldState.error} error={fieldState.error}
id={fieldState.fieldId} id={fieldState.fieldId}
{align}
{placeholder} {placeholder}
minHeight={height}
/> />
</div> {/if}
{/if} {/if}
</Field> </Field>
<style>
:global(.spectrum-Form-itemField .spectrum-Textfield--multiline) {
min-height: calc(var(--height) - 24px);
}
:global(.spectrum-Form--labelsAbove
.spectrum-Form-itemField
.spectrum-Textfield--multiline) {
min-height: calc(var(--height) - 24px);
}
</style>

View File

@ -30,6 +30,7 @@ export { default as daterangepicker } from "./DateRangePicker.svelte"
export { default as cardstat } from "./CardStat.svelte" export { default as cardstat } from "./CardStat.svelte"
export { default as spectrumcard } from "./SpectrumCard.svelte" export { default as spectrumcard } from "./SpectrumCard.svelte"
export { default as tag } from "./Tag.svelte" export { default as tag } from "./Tag.svelte"
export { default as markdownviewer } from "./MarkdownViewer.svelte"
export * from "./charts" export * from "./charts"
export * from "./forms" export * from "./forms"
export * from "./table" export * from "./table"

View File

@ -19,6 +19,8 @@
type={$notificationStore.type} type={$notificationStore.type}
message={$notificationStore.message} message={$notificationStore.message}
icon={$notificationStore.icon} icon={$notificationStore.icon}
dismissable={$notificationStore.dismissable}
on:dismiss={notificationStore.actions.dismiss}
/> />
</div> </div>
{/key} {/key}

View File

@ -25,8 +25,8 @@
} }
const proxyNotification = event => { const proxyNotification = event => {
const { message, type, icon } = event.detail const { message, type, icon, autoDismiss } = event.detail
notificationStore.actions.send(message, type, icon) notificationStore.actions.send(message, type, icon, autoDismiss)
} }
const proxyStateUpdate = event => { const proxyStateUpdate = event => {

View File

@ -19,7 +19,7 @@ const createNotificationStore = () => {
setTimeout(() => (block = false), timeout) setTimeout(() => (block = false), timeout)
} }
const send = (message, type = "info", icon) => { const send = (message, type = "info", icon, autoDismiss = true) => {
if (block) { if (block) {
return return
} }
@ -32,6 +32,7 @@ const createNotificationStore = () => {
message, message,
type, type,
icon, icon,
autoDismiss,
}, },
}) })
return return
@ -42,12 +43,20 @@ const createNotificationStore = () => {
type, type,
message, message,
icon, icon,
dismissable: !autoDismiss,
delay: get(store) != null, delay: get(store) != null,
}) })
clearTimeout(timeout) clearTimeout(timeout)
timeout = setTimeout(() => { if (autoDismiss) {
store.set(null) timeout = setTimeout(() => {
}, NOTIFICATION_TIMEOUT) store.set(null)
}, NOTIFICATION_TIMEOUT)
}
}
const dismiss = () => {
clearTimeout(timeout)
store.set(null)
} }
return { return {
@ -57,8 +66,9 @@ const createNotificationStore = () => {
info: msg => send(msg, "info", "Info"), info: msg => send(msg, "info", "Info"),
success: msg => send(msg, "success", "CheckmarkCircle"), success: msg => send(msg, "success", "CheckmarkCircle"),
warning: msg => send(msg, "warning", "Alert"), warning: msg => send(msg, "warning", "Alert"),
error: msg => send(msg, "error", "Alert"), error: msg => send(msg, "error", "Alert", false),
blockNotifications, blockNotifications,
dismiss,
}, },
} }
} }

View File

@ -1,12 +1,12 @@
{ {
"name": "@budibase/frontend-core", "name": "@budibase/frontend-core",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"description": "Budibase frontend core libraries used in builder and client", "description": "Budibase frontend core libraries used in builder and client",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",
"svelte": "src/index.js", "svelte": "src/index.js",
"dependencies": { "dependencies": {
"@budibase/bbui": "^1.0.49-alpha.14", "@budibase/bbui": "^1.0.50-alpha.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"svelte": "^3.46.2" "svelte": "^3.46.2"
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -70,9 +70,9 @@
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@apidevtools/swagger-parser": "^10.0.3", "@apidevtools/swagger-parser": "^10.0.3",
"@budibase/backend-core": "^1.0.49-alpha.14", "@budibase/backend-core": "^1.0.50-alpha.0",
"@budibase/client": "^1.0.49-alpha.14", "@budibase/client": "^1.0.50-alpha.0",
"@budibase/string-templates": "^1.0.49-alpha.14", "@budibase/string-templates": "^1.0.50-alpha.0",
"@bull-board/api": "^3.7.0", "@bull-board/api": "^3.7.0",
"@bull-board/koa": "^3.7.0", "@bull-board/koa": "^3.7.0",
"@elastic/elasticsearch": "7.10.0", "@elastic/elasticsearch": "7.10.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"description": "Handlebars wrapper for Budibase templating.", "description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs", "main": "src/index.cjs",
"module": "dist/bundle.mjs", "module": "dist/bundle.mjs",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "1.0.49-alpha.14", "version": "1.0.50-alpha.0",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -34,8 +34,8 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/backend-core": "^1.0.49-alpha.14", "@budibase/backend-core": "^1.0.50-alpha.0",
"@budibase/string-templates": "^1.0.49-alpha.14", "@budibase/string-templates": "^1.0.50-alpha.0",
"@koa/router": "^8.0.0", "@koa/router": "^8.0.0",
"@sentry/node": "^6.0.0", "@sentry/node": "^6.0.0",
"@techpass/passport-openidconnect": "^0.3.0", "@techpass/passport-openidconnect": "^0.3.0",