用Airtable, Gatsby和React构建交互式甘特图
使用Gatsby,可以很容易地将不同的数据源集成到一个应用程序中。在本文中,我们将开发一个任务管理工具,其数据取自Airtable。我们将使用React作为前端,并使用混合渲染策略。年代trong>
这是一个常见的场景:你想要开发一个连接到电子表格应用程序或其他数据源的数据的应用程序。在本文中,我将展示如何使用Gatsby框架实现这种类型的应用程序。在我们的示例应用程序中,任务将从Airtable工作区,并可视化为甘特图.用户可以通过拖放来移动任务,之后所有的更改都将与Airtable同步。你可以把这个项目用作各种调度应用程序的模板。
<我mg decoding="async" src="https://uploads.sitepoint.com/wp-content/uploads/2021/11/1636866638task-table.png" alt="一个简单的任务表" loading="lazy">
你可以在我的盖茨比云站点.项目的src文件可以在我的GitHub库.
建立项目
盖茨比是一个静态网站生成器。这意味着您使用React编写应用程序,Gatsby将您的代码转换为浏览器可以理解的HTML文件。这个构建过程是定期在<年代trong>服务器端年代trong>与传统的web应用程序相比,HTML代码首先在用户的浏览器中在客户端组装。因此,HTML文件在服务器上是静态可用的(因此称为静态站点生成器),并且可以在请求时直接发送给客户端。这减少了用户加载应用程序的时间。
必威西盟体育网页登录SitePoint的盖茨比教程提供使用此框架开发应用程序所需的所有信息。如果您希望逐步开发我的示例应用程序,您应该从下面的概要开始。
首先,您应该下载并安装node . js.您可以通过输入来检查是否正确安装节点- v
在控制台上。Node的当前版本应该显示出来:
节点- v<年代pan class="token operator">>年代pan>v14.16.0
使用Node,我们还得到了npm, Node包管理器。使用这个工具,我们现在可以安装盖茨比的CLI:
npm年代pan>安装年代pan>- g gatsby-cli
我们已经准备好使用Gatsby CLI创建一个新项目。我把它命名为“甘特-图-盖茨比”
盖茨比新甘特图盖茨比
然后使用命令移动到项目文件夹cd gantt-chart-gatsby
并使用命令构建项目盖茨比的发展
.现在您可以在浏览器上打开项目的索引页http://localhost:8000.首先,你应该只看到盖茨比为我们准备的欢迎页。
在下一步中,您应该检查src
项目文件夹。的子文件夹src /页
包含项目各个页面的React组件。现在,这对你来说足够了index.js
文件的索引页,因为在我们的示例应用程序中,我们只需要一个页面。您可以删除此文件夹中的其他文件,除了js 404.
(如果有人输入了错误的地址,这可以很有用)。
如果您覆盖现有的代码,这是一个很好的起点index.js
下面的代码:
进口年代pan>*年代pan>作为年代pan>反应年代pan>从年代pan>“反应”年代pan>常量年代pan>IndexPage年代pan>=年代pan>(年代pan>)年代pan>= >年代pan>{年代pan>返回年代pan>(年代pan><年代pan>主要<年代pan class="token operator">>年代pan><年代pan>标题<年代pan class="token operator">>年代pan>甘特年代pan>图表年代pan><年代pan>/年代pan>标题<年代pan class="token operator">>年代pan><年代pan>h1<年代pan class="token operator">>年代pan>欢迎年代pan>我的<年代pan class="token maybe-class-name">盖茨比年代pan>甘特年代pan>图表年代pan><年代pan>/年代pan>h1<年代pan class="token operator">>年代pan><年代pan>/年代pan>主要<年代pan class="token operator">>年代pan>)年代pan>}年代pan>出口年代pan>默认的年代pan>IndexPage年代pan>;年代pan>
您可以使用该命令再次构建项目盖茨比的发展
在命令行中,并在浏览器中打开索引页。现在您应该会看到空白页,标题为“欢迎来到我的盖茨比甘特图”。
用React构建前端
索引页的第一个版本
我们将把甘特图实现为一个可重用的React组件。在下面几节详细解释该组件的实现之前,我首先想说明如何初始化它并将其嵌入到索引页中。所以我建议你不要用盖茨比的发展
命令,直到我们完成组件的第一个版本。(当我们准备好了,我会让你知道!)
在这个示例项目中,我使用了“工作”和“资源”的概念。<年代trong>工作年代trong>是绘制到图表单元格中的任务,可以通过拖放来移动。<年代trong>资源年代trong>包含可移动作业所在行的标签。这些可以是任务的名称,但在其他用例中也可以是执行任务的人员、车辆或机器的名称。
作业和资源作为属性传递给甘特图组件。在将任务管理工具连接到Airtable之前,我们用JSON格式的硬编码测试数据填充列表:
进口年代pan>*年代pan>作为年代pan>反应年代pan>从年代pan>“反应”年代pan>;年代pan>进口年代pan>{年代pan>GanttChart年代pan>}年代pan>从年代pan>“. . / GanttChart”年代pan>;年代pan>进口年代pan>“. . /风格/ index.css”年代pan>;年代pan>让年代pan>j<年代pan class="token operator">=年代pan>[年代pan>{年代pan>id<年代pan class="token operator">:年代pan>“j - 1”年代pan>,年代pan>开始<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>“2021/6/1”年代pan>)年代pan>,年代pan>结束<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>“2021/6/4”年代pan>)年代pan>,年代pan>资源<年代pan class="token operator">:年代pan>“r1”年代pan>}年代pan>,年代pan>{年代pan>id<年代pan class="token operator">:年代pan>“j2”年代pan>,年代pan>开始<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>“2021/6/4”年代pan>)年代pan>,年代pan>结束<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>“2021/6/13”年代pan>)年代pan>,年代pan>资源<年代pan class="token operator">:年代pan>“r2”年代pan>}年代pan>,年代pan>{年代pan>id<年代pan class="token operator">:年代pan>:“j3”年代pan>,年代pan>开始<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>“2021/6/13”年代pan>)年代pan>,年代pan>结束<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>“2021/6/21”年代pan>)年代pan>,年代pan>资源<年代pan class="token operator">:年代pan>“r3”年代pan>}年代pan>,年代pan>]年代pan>;年代pan>让年代pan>r<年代pan class="token operator">=年代pan>[年代pan>{年代pan>id<年代pan class="token operator">:年代pan>“r1”年代pan>,年代pan>的名字<年代pan class="token operator">:年代pan>“任务1”年代pan>}年代pan>,年代pan>{年代pan>id<年代pan class="token operator">:年代pan>“r2”年代pan>,年代pan>的名字<年代pan class="token operator">:年代pan>“任务2”年代pan>}年代pan>,年代pan>{年代pan>id<年代pan class="token operator">:年代pan>“r3”年代pan>,年代pan>的名字<年代pan class="token operator">:年代pan>“任务3”年代pan>}年代pan>,年代pan>{年代pan>id<年代pan class="token operator">:年代pan>“r4”年代pan>,年代pan>的名字<年代pan class="token operator">:年代pan>“Task 4”年代pan>}年代pan>]年代pan>;年代pan>常量年代pan>IndexPage年代pan>=年代pan>(年代pan>)年代pan>= >年代pan>{年代pan>返回年代pan>(年代pan><年代pan>主要<年代pan class="token operator">>年代pan><年代pan>标题<年代pan class="token operator">>年代pan>甘特年代pan>图表年代pan><年代pan>/年代pan>标题<年代pan class="token operator">>年代pan><年代pan>h1<年代pan class="token operator">>年代pan>欢迎年代pan>我的<年代pan class="token maybe-class-name">盖茨比年代pan>甘特年代pan>图表年代pan><年代pan>/年代pan>h1<年代pan class="token operator">>年代pan><年代pan>GanttChart年代pan>工作<年代pan class="token operator">=年代pan>{年代pan>j<年代pan class="token punctuation">}年代pan>资源<年代pan class="token operator">=年代pan>{年代pan>r<年代pan class="token punctuation">}年代pan>/年代pan>>年代pan><年代pan>/年代pan>主要<年代pan class="token operator">>年代pan>)年代pan>}年代pan>;年代pan>出口年代pan>默认的年代pan>IndexPage年代pan>;年代pan>
用于甘特图的CSS样式
在下一步中,我们创建一个新的index.css
在风格
文件夹中。(如果该文件夹不存在,请创建一个新文件夹风格
在文件夹里src
这个项目。)以下CSS设置控制甘特图的布局和外观:
身体年代pan>{年代pan>字体类型年代pan>:年代pan>天线<年代pan class="token punctuation">,年代pan>海维提卡<年代pan class="token punctuation">,年代pan>无衬线<年代pan class="token punctuation">;年代pan>}年代pan># gantt-container年代pan>{年代pan>显示年代pan>:年代pan>网格<年代pan class="token punctuation">;年代pan>}年代pan>.gantt-row-resource年代pan>{年代pan>背景颜色年代pan>:年代pan>烟白年代pan>;年代pan>颜色年代pan>:年代pan>rgba年代pan>(年代pan>0年代pan>,年代pan>0年代pan>,年代pan>0年代pan>,年代pan>0.726年代pan>)年代pan>;年代pan>边境年代pan>:年代pan>1年代pan>px年代pan>固体<年代pan class="token color">rgb年代pan>(年代pan>133年代pan>,年代pan>129年代pan>,年代pan>129年代pan>)年代pan>;年代pan>text-align年代pan>:年代pan>中心<年代pan class="token punctuation">;年代pan>填充年代pan>:年代pan>15年代pan>px年代pan>;年代pan>}年代pan>.gantt-row-period年代pan>{年代pan>背景颜色年代pan>:年代pan>烟白年代pan>;年代pan>颜色年代pan>:年代pan>rgba年代pan>(年代pan>0年代pan>,年代pan>0年代pan>,年代pan>0年代pan>,年代pan>0.726年代pan>)年代pan>;年代pan>边境年代pan>:年代pan>1年代pan>px年代pan>固体<年代pan class="token color">rgb年代pan>(年代pan>133年代pan>,年代pan>129年代pan>,年代pan>129年代pan>)年代pan>;年代pan>text-align年代pan>:年代pan>中心<年代pan class="token punctuation">;年代pan>显示年代pan>:年代pan>网格<年代pan class="token punctuation">;年代pan>grid-auto-flow年代pan>:年代pan>列<年代pan class="token punctuation">;年代pan>grid-auto-columns年代pan>:年代pan>极大极小年代pan>(年代pan>40年代pan>px年代pan>,年代pan>1年代pan>fr年代pan>)年代pan>;年代pan>}年代pan>.period年代pan>{年代pan>填充年代pan>:年代pan>10年代pan>px年代pan>0年代pan>10年代pan>px年代pan>0年代pan>;年代pan>}年代pan>.gantt-row-item年代pan>{年代pan>边境年代pan>:年代pan>1年代pan>px年代pan>固体<年代pan class="token color">rgb年代pan>(年代pan>214年代pan>,年代pan>214年代pan>,年代pan>214年代pan>)年代pan>;年代pan>填充年代pan>:年代pan>10年代pan>px年代pan>0年代pan>10年代pan>px年代pan>0年代pan>;年代pan>位置年代pan>:年代pan>相对<年代pan class="token punctuation">;年代pan>背景颜色年代pan>:年代pan>白色年代pan>;年代pan>}年代pan>.job年代pan>{年代pan>位置年代pan>:年代pan>绝对<年代pan class="token punctuation">;年代pan>高度年代pan>:年代pan>38年代pan>px年代pan>;年代pan>前年代pan>:年代pan>5年代pan>px年代pan>;年代pan>z - index年代pan>:年代pan>One hundred.年代pan>;年代pan>背景颜色年代pan>:年代pan>rgb年代pan>(年代pan>167年代pan>,年代pan>171年代pan>,年代pan>245年代pan>)年代pan>;年代pan>光标年代pan>:年代pan>指针<年代pan class="token punctuation">;年代pan>}年代pan>
实现GanttChart
组件
的实现GanttChart
组件的详细信息。首先,我们需要一个名为GanttChart.js
在src
文件夹中。的简化版本GanttChart
只有一个月(2021年6月)。可以在GitHub上找到一个扩展版本,其中包含开始月份和结束月份的选择字段GanttChart_extended.js.
图表的建立分为三个步骤,以函数表示initFirstRow
,initSecondRow
而且initGanttRows
:
进口年代pan>反应年代pan>从年代pan>“反应”年代pan>;年代pan>出口年代pan>类年代pan>GanttChart年代pan>扩展年代pan>反应<年代pan class="token punctuation">.年代pan>组件年代pan>{年代pan>的名字<年代pan class="token operator">=年代pan>[年代pan>“1月”年代pan>,年代pan>“2月”年代pan>,年代pan>“3”年代pan>,年代pan>“4月”年代pan>,年代pan>“可能”年代pan>,年代pan>“君”年代pan>,年代pan>“7”年代pan>,年代pan>“8月”年代pan>,年代pan>“9”年代pan>,年代pan>“10月”年代pan>,年代pan>“11月”年代pan>,年代pan>“12月”年代pan>]年代pan>;年代pan>构造函数年代pan>(年代pan>道具年代pan>)年代pan>{年代pan>超级年代pan>(年代pan>道具<年代pan class="token punctuation">)年代pan>;年代pan>这年代pan>.年代pan>状态年代pan>=年代pan>{年代pan>dateFrom<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>2021年代pan>,年代pan>5年代pan>,年代pan>1年代pan>)年代pan>,年代pan>dateTo<年代pan class="token operator">:年代pan>新年代pan>日期年代pan>(年代pan>2021年代pan>,年代pan>5年代pan>,年代pan>30.年代pan>)年代pan>,年代pan>}年代pan>;年代pan>}年代pan>渲染年代pan>(年代pan>)年代pan>{年代pan>让年代pan>月<年代pan class="token operator">=年代pan>新年代pan>日期年代pan>(年代pan>这年代pan>.年代pan>状态年代pan>.年代pan>dateFrom年代pan>.年代pan>getFullYear年代pan>(年代pan>)年代pan>,年代pan>这年代pan>.年代pan>状态年代pan>.年代pan>dateFrom年代pan>.年代pan>getMonth年代pan>(年代pan>)年代pan>,年代pan>1年代pan>)年代pan>;年代pan>让年代pan>grid_style<年代pan class="token operator">=年代pan>“100 px fr”年代pan>;年代pan>让年代pan>firstRow<年代pan class="token operator">=年代pan>这年代pan>.年代pan>initFirstRow年代pan>(年代pan>月<年代pan class="token punctuation">)年代pan>;年代pan>让年代pan>secondRow<年代pan class="token operator">=年代pan>这年代pan>.年代pan>initSecondRow年代pan>(年代pan>月<年代pan class="token punctuation">)年代pan>;年代pan>让年代pan>ganttRows<年代pan class="token operator">=年代pan>这年代pan>.年代pan>initGanttRows年代pan>(年代pan>月<年代pan class="token punctuation">)年代pan>;年代pan>返回年代pan>(年代pan><年代pan>div类名<年代pan class="token operator">=年代pan>“甘特图”年代pan>>年代pan><年代pan>div id<年代pan class="token operator">=年代pan>“gantt-container”年代pan>风格<年代pan class="token operator">=年代pan>{年代pan>{年代pan>gridTemplateColumns<年代pan class="token operator">:年代pan>grid_style<年代pan class="token punctuation">}年代pan>}年代pan>>年代pan>{年代pan>firstRow<年代pan class="token punctuation">}年代pan>{年代pan>secondRow<年代pan class="token punctuation">}年代pan>{年代pan>ganttRows<年代pan class="token punctuation">}年代pan><年代pan>/年代pan>div<年代pan class="token operator">>年代pan><年代pan>/年代pan>div<年代pan class="token operator">>年代pan>)年代pan>;年代pan>}年代pan>initFirstRow年代pan>(年代pan>月年代pan>)年代pan>{年代pan>…年代pan>}年代pan>initSecondRow年代pan>(年代pan>月年代pan>)年代pan>{年代pan>…年代pan>}年代pan>initGanttRows年代pan>(年代pan>月年代pan>)年代pan>{年代pan>…年代pan>}年代pan>/ /辅助功能:年代pan>formatDate年代pan>(年代pan>d年代pan>)年代pan>{年代pan>返回年代pan>d<年代pan class="token punctuation">.年代pan>getFullYear年代pan>(年代pan>)年代pan>+年代pan>“-”年代pan>+年代pan>这年代pan>.年代pan>zeroPad年代pan>(年代pan>d<年代pan class="token punctuation">.年代pan>getMonth年代pan>(年代pan>)年代pan>+年代pan>1年代pan>)年代pan>+年代pan>“-”年代pan>+年代pan>这年代pan>.年代pan>zeroPad年代pan>(年代pan>d<年代pan class="token punctuation">.年代pan>获取当前日期年代pan>(年代pan>)年代pan>)年代pan>;年代pan>}年代pan>zeroPad年代pan>(年代pan>n年代pan>)年代pan>{年代pan>返回年代pan>n<年代pan class="token operator"><年代pan>10年代pan>?年代pan>“0”年代pan>+年代pan>n<年代pan class="token operator">:年代pan>n<年代pan class="token punctuation">;年代pan>}年代pan>monthDiff年代pan>(年代pan>d1<年代pan class="token punctuation">,年代pan>d2年代pan>)年代pan>{年代pan>让年代pan>个月<年代pan class="token punctuation">;年代pan>个月<年代pan class="token operator">=年代pan>(年代pan>d2<年代pan class="token punctuation">.年代pan>getFullYear年代pan>(年代pan>)年代pan>-年代pan>d1<年代pan class="token punctuation">.年代pan>getFullYear年代pan>(年代pan>)年代pan>)年代pan>*年代pan>12年代pan>;年代pan>个月<年代pan class="token operator">- =年代pan>d1<年代pan class="token punctuation">.年代pan>getMonth年代pan>(年代pan>)年代pan>;年代pan>个月<年代pan class="token operator">+ =年代pan>d2<年代pan class="token punctuation">.年代pan>getMonth年代pan>(年代pan>)年代pan>;年代pan>返回年代pan>个月<年代pan class="token operator">< =年代pan>0年代pan>?年代pan>0年代pan>:年代pan>个月<年代pan class="token punctuation">;年代pan>}年代pan>dayDiff年代pan>