任务管理是企业最重要的功能之一。虽然这个问题有很多解决方案,但还没有灵丹妙药,因为每个业务领域都有自己的特点。在这种情况下开发满足特定要求的应用程序并不少见。 AllcountJS 允许您从头开始非常快速地构建自定义任务管理应用程序。
如果您不熟悉 AllcountJS,请先查看此
入门
指南。虽然 AllcountJS 允许您使用 Node.js 的所有功能,但在本文中我们将仅使用 App Config 代码。为了运行演示代码,您应该先执行
npm install allcountjs-cli
,然后执行
allcountjs init
,或者直接
从
我们的演示页面运行代码,您将得到如下内容:
模型
让我们从模型声明开始。任务管理中最重要的事情可能是拥有一个任务对象(显然)和一些状态流。让我们在
main.js
中定义我们的模型:
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
此 App Config 生成一个工作应用程序,该应用程序具有两个实体:Task 和 Status。任务对象具有摘要和截止日期字段以及状态参考。状态实体有一个名称字段用作参考名称,同时显示一个组合框和一个顺序字段,稍后将用于定义状态的顺序。如您所见,必填字段标有
.required()
。这意味着在填写这些字段之前无法创建或保存实体。您还可以注意到
onlyAuthenticated
标志,该标志指定未经身份验证无法访问应用程序。
状态顺序
我们可以通过添加
sorting: [['order', 1]],
到
Status
实体类型来定义我们的状态优先级:
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
此声明指示 AllcountJS 按顺序字段按升序对
Status
实体进行排序。
板视图
AllcountJS 最强大的功能之一是视图概念。视图也是一个实体,但作为存储,它使用另一个实体。因此,有机会为同一数据源创建多个行为和可视化。让我们通过添加以下属性为我们的
Task
实体创建一个板视图
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
并创建新的菜单项以打开面板:
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
我们还应该创建我们引用的自定义视图板(
board.jade
)
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
AllcountJS 默认使用
jade 模板语言
。
board.jade
中的代码定义了我们板的自定义视图的模板。它定义了描述卡片外观的
panelBody
块。我们应该得到
main.js
的以下结果
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
如果您运行此代码示例,您将看到带有状态的看板,您可以在其中在状态之间移动卡片。由于排序,状态顺序由
order
字段定义。
抛光
为了完善您可能想要为菜单项和应用程序添加图标的东西。您可以通过简单地参考
Font Awesome 图标
来做到这一点。让我们为菜单添加
appIcon
和图标,我们将获得应用程序的最终版本。
A.app({
appName: "Task manager",
onlyAuthenticated: true,
menuItems: [
{
name: "Planning",
entityTypeId: "Task"
}, {
name: "Statuses",
entityTypeId: "Status"
}
],
entities: function(Fields) {
return {
Task: {
fields: {
summary: Fields.textarea("Summary").required(),
dueDate: Fields.date("Due Date").required(),
status: Fields.fixedReference("Status", "Status")
}
},
Status: {
fields: {
name: Fields.text("Name").required(),
order: Fields.integer("Order").required()
},
referenceName: "name"
}
}
}
});
尝试在我们的 演示库 中运行它。