12分钟阅读

创建带空调和反应的现场仪表板

迪伦是一家全堆栈工程师,拥有丰富的各种行业,包括电子商务,医疗保健和专业服务。

一家公司是否是一个大型企业或崭露头角的创业,从用户和客户收集数据,并报告或可视化该数据对业务至关重要。

我最近与基于巴西的远程医疗启动。其使命是通过将患者连接到医疗专业人员和健康教练来提供远程护理和监控。核心需求是为教练和健康专业人员创建一个界面,以便轻松审查患者的信息和与其特定情况相关的最重要的指标:仪表板。

输入TypeForm和AirTable。

typeform.

typeform. 是一个转到数据收集工具之一,可以为完成调查的用户实现响应的Web体验。它还配备了几个功能,使调查更加智能,特别是在组合时:

  • 逻辑跳跃
  • 隐藏的字段

可以通过URL共享调查,该URL可以预先种植隐藏字段的值,然后可以用于实现逻辑跳转并改变具有链接的用户的调查的行为。

空调用途

空调 是电子表格数据库混合动力车和协作云平台。它的重点是点,单击功能意味着非技术用户可以在不编码的情况下配置。 AirTable在任何业务或项目中都有多种用例。

您可以使用Airtable Base:

  • CRM. (客户关系管理)
  • HRIS. (人力资源信息系统)
  • 项目管理
  • 内容规划
  • 活动策划
  • 用户反馈

还有更多的潜在用例。您可以探索空中案例研究 这里.

如果您不熟悉AirTable,则概念数据模型如下所示:

  • 工作区 - 由...组成的 基地
  • 根据 - 由...组成的 桌子
  • 桌子 - 由...组成的 领域 (columns) and rows
  • 看法 - 表数据的透视图,具有可选过滤器和缩小字段
  • 场地 - 具有字段类型的表的列;看 这里 有关的更多信息 现场类型

除了提供具有熟悉的电子表格功能的云托管数据库,这里有一些平台如此强大的原因:

对使用空调的技术和非技术用户的描述。

对于非技术用户,AirTable提供:

  • 易于使用的前端接口
  • 可以用点击配置创建的自动化,以发送电子邮件,处理数据行,日历中的时间表约会,以及更多
  • 多种类型的视图,允许团队在同一基础和表格上进行协作
  • 可从市场安装的空中应用程序来增强基地

对于开发人员来说,AirTable提供:

  • 记录良好的后端API
  • 脚本环境,允许开发人员在基础内自动执行操作
  • 也可以触发在空中环境中运行的自定义开发脚本的自动化,扩展了自动化的功能

您可以在空调中了解更多信息 这里.

入门:TypeForm To AirTable

TypeForm调查已由客户端配置,下一步是规划数据如何将其降落在空气中,然后将其变成仪表板。在任何数据库之上创建仪表板时有许多问题需要考虑: 我们应该如何构建数据?在可视化之前需要处理哪些数据?我们应该使用Google Shotes同步基础并使用Google数据工作室吗?我们应该出口并找到另一个第三方工具吗?

幸运的是,对于开发人员来说,不仅空载性提供自动化和脚本来处理数据处理步骤,而且还可以使用空中应用程序在空载基础上构建自定义应用程序和接口。

AirTable的自定义应用程序

自定义应用程序以来已经存在,因为Airtable Blocks SDK发布了 2018年初,而且是 最近重命名为应用程序。块的释放是巨大的,因为它意味着创造者现在有能力开发,因为空调使它成为“无限重新组织的乐高套件”。

最近更改了应用程序, 空中市场 也可以公开分享应用程序。

AirTable Apps提供具有无限重新组织的乐高套件的业务,他们可以根据自己的需求定制。

为了在Airtable中构建自定义应用程序,a JavaScript开发人员 必须知道如何使用 反应是一个用于构建用户界面的最受欢迎的JavaScript库之一。 AirTable提供了功能性反应组件和挂钩的组件库,这是迅速构建一致的UI并确定如何在应用程序及其组件中管理状态的巨大帮助。

查看AirTable 入门 文章有关更多信息和空调 GitHub. 有关应用的示例。

空气仪表板要求

在使用客户团队审核仪表板模型后,要使用的数据类型清晰。我们需要一系列仪表板组件,该组件将显示为仪表板上的文本以及可以随时间跟踪的不同度量标准的图表。

需要为每个患者构建自定义仪表板的教练和医疗专业人士,因此我们需要一个灵活的方法来添加和删除图表。无论选择患者,都会显示相对于每个患者的其他静态数据。

在这种情况下,仪表板部分煮沸到:

  • 一般信息 - 患者姓名,电子邮件,电话号码,联系人首选,出生日期,年龄
  • 目标 - 患者基于调查结果的目标
  • 一些统计数据 - BMI,身高和体重
  • 药物使用 - 列出患者已经使用的所有处方药
  • 家庭病史 - 有助于诊断某些条件
  • 图表 - Airtable Dashboard用户可以添加图表的部分,并配置它会随时间可视化的度量标准

显示一个空气仪表板样机的图象。

除图表之外的所有部分的一种方法是将目标,药物使用和家族历史的所有列硬编码到仪表板中。但是,这不允许客户团队将新问题添加到TypeForm Survey,并将新列添加到AirTable表中,以显示仪表板上的数据而无需开发人员更新自定义应用程序。

对这一挑战更优雅和可扩展的解决方案正在寻找一种方法 标签 与特定仪表板部分相关的列,并使用空调使用时的元数据检索这些列 桌子场地 models.

这是使用字段描述来实现的,作为从表中标记列的位置,与要显示给用户的仪表板部分相关的列。然后,我们可以只能确保具有创建者角色(管理员)的那些对基础的角色有能力修改这些字段描述以改变仪表板上出现的内容。为了说明此解决方案,我们将主要关注一般信息中的项目以及如何呈现图表。

创建#ag#系统

Given the dashboard sections, it made sense to make reusable tags for some sections and specific tags for certain columns. For items like patient name, email, and phone number, #NAME#, #EMAIL#, and #PHONE# were added to each Field’s description, respectively. That would allow that information to be retrieved via the Table metadata like this:

const name = table ? table.fields.filter(field => field.description?.includes("#NAME#"))

对于需要从许多标记的列中绘制的仪表板的区域,我们将为每个仪表板部分具有以下标记:

  • obj - 目标
  • FAM - 家庭历史
  • MED - 医学用法
  • 可以 - 癌症的家族史
  • 图表 - 任何应源于添加图表的列;必须是数量

In addition, it was important to separate the name of a column in a Table from the label it would receive on the dashboard, so anything that received a #TAG# would also have the ability to receive two #LABEL# tags in its Field Description. A Field Description would look like this:

屏幕截图展示了在字段描述中使用标签。

In case the #LABEL# tags are missing, we will display the column name from the Table.

在使用上一个代码示例检索字段后,我们可以在描述中解析在描述中设置的标签,如下检索字段:

// utils.js

export const setLabel = (field, labelTag = "#LABEL#") => {
   const labelTags = (field.description?.match(new RegExp(labelTag, "g")) || []).length;
   let label;
   if (labelTags === 2) label = field.description?.split(`${labelTag}`)[1];
   if (!label || label?.trim() === '') label = field.name;
   return {...field, label, name: field.name, description: field.description};
}

With this #TAG# system, we achieve three main things:

  • 可以根据需要更改表中的列名(字段)。
  • 仪表板中的数据标签可以与列名不同。
  • 仪表板部分的目标,医学用法,家庭历史和图表可以由客户团队更新 不触摸代码线。

持久状态

在反应中,我们使用状态并将其传递给组件作为道具,以便在其状态更改时重新渲染该组件。通常,这与燃料仪表板组件的API调用相关联,但在空气中,我们已经拥有了所有数据,并且只需过滤基于我们正在查看的患者所显示的内容。此外,如果我们使用状态,它将不会持续到仪表板本身的刷新中的数据。

那么,我们如何持续一个值过去刷新以保持仪表板过滤?幸运的是,Airtable为这提供了一个叫做的钩子 useglobalconfig 其中,它在仪表板上维护一个关键级值商店,用于应用程序安装。当应用程序加载到仪表板组件时,我们只需实现从此键值存储中检索值的检索值的逻辑。

What is even more useful about using the useglobalconfig hook is that when its values are set, the dashboard component and its child components re-render, so you can use the Global Config like you would use a state variable in a typical React implementation.

介绍图表

AirTable提供了图表的示例 简单的图表应用程序,它使用 反应图表,反应包装器 Chart.js. (chart-ception).

在简单的图表应用程序中,我们为整个应用程序有一个图表,但在我们的仪表板应用程序中,我们需要用户从自己的仪表板中添加和删除自己的图表。更重要的是,在与客户团队的讨论中,似乎在同一图表上会更好地查看某些指标(比如舒张和收缩压的读数)。

有了这个,我们有以下物品来解决:

  • 每个用户的图表的持久状态(甚至使用Global Config)
  • 每张图表允许多个度量标准

这是全局配置的权力在方便的地方,因为我们可以使用键值存储来维护所选的指标以及其他关于我们的图表列表的任何其他指标。当我们在UI中配置图表时,图表组件本身将由于全局配置的更新而重新呈现。对于仪表板的图表部分,这里是一个 要旨 使用组件供参考,重点关注 仪表板图表.JS.单图表.

桌子 传递给每个图表是用于它的元数据找到字段的内容,而 记录 passed have already been filtered by the patient selected at the top-level dashboard component that imports dashboard_charts/index.js.

Note that the fields listed as options in the dropdown for a chart are pulled using the #CHART# 标签 we mentioned before, with this line in a useEffect hook:

// single_chart/index.js

…
useEffect(() => {
  (async () => {

...

    if (table) {
      const tempFieldOptions = table.fields.filter(field =>    
        field.description?.includes('#CHART#')).map(field => {
          return {
            ...setLabel(field),
            value: field.id
          }
       });
       setFieldSelectOptions([...tempFieldOptions]);
    }
  })();
}, [table, records, fields]);


...

这 code above shows how the setLabel function referenced earlier is used with the #TAG# to add anything provided in the #LABEL# tags and display it for the option in the field dropdown.

我们的图表组件利用了Chart.js提供的多轴功能,如图所示 反应图表。我们刚刚通过UI扩展了它,用户可以添加数据集和图表类型(行或栏)。

使用Global Config的关键是在这种情况下,要知道每个密钥只能保存字符串|布尔|号码| null | GlobalConfigarray | GlobalConfigObject(参见 全局配置值参考)。

我们拥有以下项目以维持:

  • ChartTitle. 它是自动化的,可以由用户重命名
  • 领域 每个项目的数组:
    • 场地 从空中透气的场景
    • ChartOption. 作为一行|酒吧作为 Chart.js.文档 indicate
    • 颜色 作为Colorutils的空气颜色
    • 十六进制 作为与空气颜色有关的十六进制代码

要管理此问题,我发现最方便地将此数据作为对象将此数据完全合作而不是设置全局配置密钥和值一直向下。请参阅下面的示例(globalconfig.json. 在GIST中,包括全局配置值,以过滤患者的记录和用于支持TYPEAHING滤波组件的某些相关变量(感谢 反应-Bootstrap-typeahead):

{
 "xCharts": {
   "chart-1605425876029": "{\"领域\":[{\"场地\":\"fldxLfpjdmYeDOhXT\",\"ChartOption.\":\"line\",\"颜色\":\"blueBright\",\"十六进制\":\"#2d7ff9\"},{\"场地\":\"fldqwG8iFazZD5CLH\",\"ChartOption.\":\"line\",\"颜色\":\"blueLight1\",\"十六进制\":\"#9cc7ff\"}],\"ChartTitle.\":\"Gráfico criado em 11/15/2020, 2:37:56 AM\"}",
   "chart-1605425876288": "{\"领域\":[{\"场地\":\"fldGJZIdRlq3V3cKu\",\"ChartOption.\":\"line\",\"颜色\":\"blue\",\"十六进制\":\"#1283da\"}],\"ChartTitle.\":\"Gráfico criado em 11/15/2020, 2:37:56 AM\"}",
   "chart-1605425876615": "{\"领域\":[{\"场地\":\"fld1AnNcfvXm8DiNs\",\"ChartOption.\":\"line\",\"颜色\":\"blueLight1\",\"十六进制\":\"#9cc7ff\"},{\"场地\":\"fldryX5N6vUYWbdzy\",\"ChartOption.\":\"line\",\"颜色\":\"blueDark1\",\"十六进制\":\"#2750ae\"}],\"ChartTitle.\":\"Gráfico criado em 11/15/2020, 2:37:56 AM\"}",
   "chart-1605425994036": "{\"领域\":[{\"场地\":\"fld9ak8Ja6DPweMdJ\",\"ChartOption.\":\"line\",\"颜色\":\"blueLight2\",\"十六进制\":\"#cfdfff\"},{\"场地\":\"fldxVgXdZSECMVEj6\",\"ChartOption.\":\"line\",\"颜色\":\"blue\",\"十六进制\":\"#1283da\"}],\"ChartTitle.\":\"Gráfico criado em 11/15/2020, 2:39:54 AM\"}",
   "chart-1605430015978": "{\"领域\":[{\"场地\":\"fldwdMJkmEGFFSqMy\",\"ChartOption.\":\"line\",\"颜色\":\"blue\",\"十六进制\":\"#1283da\"},{\"场地\":\"fldqwG8iFazZD5CLH\",\"ChartOption.\":\"line\",\"颜色\":\"blueLight1\",\"十六进制\":\"#9cc7ff\"}],\"ChartTitle.\":\"New Chart\"}",
   "chart-1605430916029": "{\"领域\":[{\"场地\":\"fldCuf3I2V027YAWL\",\"ChartOption.\":\"line\",\"颜色\":\"blueLight1\",\"十六进制\":\"#9cc7ff\"},{\"场地\":\"fldBJjtRkWUTuUf60\",\"ChartOption.\":\"line\",\"颜色\":\"blueDark1\",\"十六进制\":\"#2750ae\"}],\"ChartTitle.\":\"Gráfico criado em 11/15/2020, 4:01:56 AM\"}",
   "chart-1605431704374": "{\"领域\":[{\"场地\":\"fld7oBtl3iiHNHqoJ\",\"ChartOption.\":\"line\",\"颜色\":\"blue\",\"十六进制\":\"#1283da\"}],\"ChartTitle.\":\"Gráfico criado em 11/15/2020, 4:15:04 AM\"}"
 },
 "xPatientEmail": "[email protected]",
 "xTypeaheadValue": "Elle Gold ([email protected])",
 "xSelectedValue": "[{\"label\":\"Elle Gold ([email protected])\",\"id\":\"[email protected]\",\"name\":\"Elle Gold\",\"email\":\"[email protected]\"}]"
}

笔记: 上面包含的所有数据以及下面的动画中包含的数据不是真正的患者数据。

这是一个最终结果的看法:

Animated显示空载仪表板UI。

那个the the the the the the the the the the?

为了患者过滤,我们需要一种选择患者的方法,然后根据该患者过滤记录。在本节中,我们审查了这一目标。

对于typeahead, 反应-Bootstrap-typeahead 作为一个简单的选择,因为剩下的唯一步骤正在为typeahead准备选项,将其与空调输入混合以进行造型和加载引导,以及我们菜单的其他一些样式。从您最喜爱的组件库中将组件丢弃到AirTable应用程序中并不像典型的反应Web开发中那样简单;但是,只有几个额外的步骤让所有东西都能看出你的期望。

这是最终结果:

动画GIF展示了逐患者的功能。

要呈现空气输入并保持所有风格一致,Reftor-Bootstrap-TypeaHead附带ReveryInput Prop。查看更多有关如何修改组件的渲染 这里.

对于Bootstrap样式并覆盖我们的菜单项,从AirTable使用以下两个UILS:

Frontend.js. 在The Gist的摘录中的摘录。

此行用于全局加载Bootstrap:

// frontend/index.js

loadCSSFromURLAsync('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css');

你会注意到一些 添加逻辑 for things like handling style changes on hover or restyling links (<a></a>) to get the familiar bootstrap look and feel. This also includes the handling of 设置全局配置值 对于记录的类型和过滤,以便如果用户离开其仪表板,请刷新其页面,或者希望与其他人分享此仪表板,该应用程序仍然存在仪表板应用程序中的选定患者。这也允许用户在与选择或不同图表的不同患者的相同空中仪表板中并排在同一空中仪表板中安装多个副本。

请记住,Airtable中的仪表板也可供基础的所有用户使用,因此仪表板上的这些自定义应用程序将被过滤给同一患者和图表,无论哪些用户都同时查看仪表板。

让我们回顾我们覆盖的东西:

  1. AirTable允许非技术用户和技术用户在AirTable中进行协作。
  2. TypeForm附带了一种空中集成,允许非技术用户将TypeForm结果映射到Airtable。
  3. 无论是从市场上选择或建造自定义应用程序,AirTable Apps提供了一种强大的方式来提升其空气基地。
  4. 开发人员可以在几乎任何可想而可以使用这些应用程序的方式迅速扩展空气。我们上面的例子只花了三周的时间来设计和实施(当然,现有图书馆的巨大帮助)。
  5. A #TAG# system can be used to modify the dashboard without requiring code changes by developers. There are better and worse use cases for this. Be sure to limit permissions to the Creator role if using this strategy.
  6. 使用Global Config允许开发人员在应用程序安装中持久。将其与您的状态管理策略混合给您的组件的种子数据。
  7. Don’t expect to drag and drop components from other libraries and projects directly into your Airtable App. Styles can be loaded using the loadcssfromstring.loadcssfromurlasync. utils provided by Airtable.

未来打样

使用更复杂的中间件

使用TypeForf和AirTable,将问题的映射配置为列很容易且经济高效。

但是,有一个大缺点:如果您有一个超过100个问题的调查映射到aigtable并且需要修改映射,必须删除整个映射并重新开始。这显然不是理想的,而是为了免费一体化,我们可以处理这个。

其他选项将有一个 Zapier. (或类似)集成管理TypeForm和AirTable之间的数据。该调度您可以在不从划痕中开始修改任何列的任何问题的映射。这将有自己的成本考虑因素也是如此。

希望,这里的一些经验教训将帮助寻求使用空调构建解决方案的人。

最后,你可以看看 与文件讨论的文件 in this article.

理解基础知识

是空调的关系数据库吗?

简而言之,是的。数据与关系数据库类似地组织,但不需要相同的脚本知识来搅打您自己的空中(数据)基础。另一个主要差异是空气能够保持的数据量(行/记录的数量/记录数)(Pro计划上的每碱度为50,000)。

什么是空气的好处?

空调可用作数据库和用户界面,以在同一数据上进行协作,没有必需的编码。它将电子表格的所有熟悉程度与与关系数据库类似的强度相结合。您还可以使用自动化和应用程序的增压,以及它有一个API。

什么是类型的类型用于?

typeform.是一个数据收集工具,允许您通过URL创建表单并收集响应。其优势在其用户体验中,响应界面,集成到其他工具,以及创建逻辑跳跃和隐藏字段的能力,以根据响应或预先种植数据来修改用户的调查体验。

可免费使用可免费使用吗?

是的,有一个免费的层,但是为了构建自定义应用程序或使用市场使用应用程序,需要一个Pro订阅。

typeform.是免费的吗?

有一个免费的第一层可以开始,但是需要一项付费计划来使用内置的集成(Airtable,MailChimp),并通过免费计划的限制。