我使用KeystoneJS和PostgreSQL作为我的后端,阿波罗在我的应用程序的前端。我有一个架构,它的列表链接到另一个列表。我希望能够允许用户更改第二个列表的顺序。
这是我的模式的简化版本。
keystone.createList(
'forms',
{
fields: {
name: {
type: Text,
isRequired: true,
},
buttons: {
type: Relationship,
ref: 'buttons.attached_forms',
many: true,
},
},
}
);
keystone.createList(
'buttons',
{
fields: {
name: {
type: Text,
isRequired: true,
},
attached_forms: {
type: Relationship,
ref: 'forms.buttons',
many: true,
},
},
}
);因此,我想做的是,允许用户更改按钮的顺序,以便将来从表单中获取按钮:
const QUERY = gql`
query getForms($formId: ID!) {
allforms(where: {
id: $formId,
}) {
id
name
buttons {
id
name
}
}
}
`;按钮应该以预定义的顺序从后端返回。
{
id: 1,
name: 'Form 1',
buttons: [
{
id: 1,
name: 'Button 1',
},
{
id: 3,
name: 'Button 3',
},
{
id: 2,
name: 'Button 2',
}
]
}甚至还有一些返回的数据和查询,这些数据将允许根据用户定义的前端排序顺序进行排序。
问题是,这种关系对许多人来说是多方面的。
因此,仅仅在按钮模式中添加列是不够的,因为排序需要特定于关系。换句话说,如果用户将一个特定的按钮放在特定的表单上,它不应该更改其他表单上相同按钮的顺序。
在我自己创建的后端中,我会向联接表中添加一些内容,比如sortOrder字段或类似的字段,然后更改这些值以更改顺序,甚至在前端使用该信息对它们进行排序。有点像这个答案在这里。多到多连接表将有像formId、buttonId、sortOrder这样的列。
我一直在钻研KeystoneJS的文档,我想不出一种方法,在不使用我们正在使用的KnexAdapter的情况下,让它工作下去。
我正在使用:
{
"@keystonejs/adapter-knex": "^11.0.7",
"@keystonejs/app-admin-ui": "^7.3.11",
"@keystonejs/app-graphql": "^6.2.1",
"@keystonejs/fields": "^20.1.2",
"@keystonejs/keystone": "^17.1.2",
"@keystonejs/server-side-graphql-client": "^1.1.2",
}对我如何做到这一点有什么想法吗?
发布于 2021-02-09 22:50:23
一种方法是有两个“按钮”列表,一个带有一个按钮的模板(下面是buttonTemplate),带有诸如名称等公共数据,另一个(button )引用一个buttonTemplate和一个form。这允许您将一个formIndex属性分配给每个button,该属性指示其在相应窗体上的位置。
(未经测试)示例代码:
keystone.createList(
'Form',
{
fields: {
name: {
type: Text,
isRequired: true,
},
buttons: {
type: Relationship,
ref: 'Button.form',
many: true,
},
},
}
);
keystone.createList(
'Button',
{
fields: {
buttonTemplate: {
type: Relationship,
ref: 'ButtonTemplate.buttons',
many: false,
},
form: {
type: Relationship,
ref: 'Form.buttons',
many: false,
},
formIndex: {
type: Integer,
isRequired: true,
},
},
}
);
keystone.createList(
'ButtonTemplate',
{
fields: {
name: {
type: Text,
isRequired: true,
},
buttons: {
type: Relationship,
ref: 'Button.buttonTemplate',
many: true,
},
},
}
);我认为,与buttonOrder解决方案相比,这不太可能给您带来麻烦(我相信您可以看到这一点),例如用户删除该字段引用的按钮。
如果您确实决定采用这种方法,您可以在Keystone中使用钩子功能来防范此类问题。例如,在button是已删除之前,遍历所有表单并重写buttonOrder字段,删除对已删除按钮的任何引用。
发布于 2021-02-04 17:02:51
我曾经遇到过类似的挑战,所以在进行了一些研究并找到了这个回答之后,我使用PostgreSQL触发器实现了一个项目的解决方案。
因此,您可以添加一个触发器,在更新时,它应该移动buttonOrder。
下面是我所使用的SQL,这是测试代码,我用regex替换了条件,以适应您的问题:)
// Assign order
await knex.raw(`
do $$
DECLARE form_id text;
begin
CREATE SEQUENCE buttons_order_seq;
CREATE VIEW buttons_view AS SELECT * FROM "buttons" ORDER BY "createdAt" ASC, "formId";
CREATE RULE buttons_rule AS ON UPDATE TO buttons_view DO INSTEAD UPDATE buttons SET order = NEW.order WHERE id = NEW.id;
FOR form_id IN SELECT id FROM form LOOP
ALTER SEQUENCE buttons_order_seq RESTART;
UPDATE buttons_view SET order = nextval('buttons_order_seq') WHERE "formId" = form_id;
END LOOP;
DROP SEQUENCE buttons_order_seq;
DROP RULE buttons_rule ON buttons_view;
DROP VIEW buttons_view;
END; $$`);
// Create function that shifts orders
await knex.raw(`
CREATE FUNCTION shift_buttons_order()
RETURNS trigger AS
$$
BEGIN
IF NEW.order < OLD.order THEN
UPDATE buttons SET order = order + 1, "shiftOrderFlag" = NOT "shiftOrderFlag"
WHERE order >= NEW.order AND order < OLD.order AND "formId" = OLD."formId";
ELSE
UPDATE buttons SET order = order - 1, "shiftOrderFlag" = NOT "shiftOrderFlag"
WHERE order <= NEW.order AND order > OLD.order AND "formId" = OLD."formId";
END IF;
RETURN NEW;
END;
$$
LANGUAGE 'plpgsql'`);
// Create trigger to shift orders on update
await knex.raw(`
CREATE TRIGGER shift_buttons_order BEFORE UPDATE OF order ON buttons FOR EACH ROW
WHEN (OLD."shiftOrderFlag" = NEW."shiftOrderFlag" AND OLD.order <> NEW.order)
EXECUTE PROCEDURE shift_buttons_order()`);发布于 2021-02-03 20:31:34
我们提出的一个选项是将订单添加到表单表中。
keystone.createList(
'forms',
{
fields: {
name: {
type: Text,
isRequired: true,
},
buttonOrder: {
type: Text,
},
buttons: {
type: Relationship,
ref: 'buttons.attached_forms',
many: true,
},
},
}
);这个新字段buttonOrder可以包含按钮in顺序的字符串表示形式,就像JSON字符串化数组中的那样。这方面的主要问题是,很难使该字段与实际的链接按钮保持同步。
https://stackoverflow.com/questions/66034621
复制相似问题