首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >KeystoneJs用户定义的关系顺序

KeystoneJs用户定义的关系顺序
EN

Stack Overflow用户
提问于 2021-02-03 19:45:55
回答 3查看 521关注 0票数 3

我使用KeystoneJS和PostgreSQL作为我的后端,阿波罗在我的应用程序的前端。我有一个架构,它的列表链接到另一个列表。我希望能够允许用户更改第二个列表的顺序。

这是我的模式的简化版本。

代码语言:javascript
复制
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,
        },
      },
    }
);

因此,我想做的是,允许用户更改按钮的顺序,以便将来从表单中获取按钮:

代码语言:javascript
复制
const QUERY = gql`
  query getForms($formId: ID!) {
    allforms(where: {
      id: $formId,
    }) {
      id
      name
      buttons {
        id
        name
      }
    }
  }
`;

按钮应该以预定义的顺序从后端返回。

代码语言:javascript
复制
{
    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的情况下,让它工作下去。

我正在使用:

代码语言:javascript
复制
{
    "@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",
}

对我如何做到这一点有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-02-09 22:50:23

一种方法是有两个“按钮”列表,一个带有一个按钮的模板(下面是buttonTemplate),带有诸如名称等公共数据,另一个(button )引用一个buttonTemplate和一个form。这允许您将一个formIndex属性分配给每个button,该属性指示其在相应窗体上的位置。

(未经测试)示例代码:

代码语言:javascript
复制
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字段,删除对已删除按钮的任何引用。

票数 2
EN

Stack Overflow用户

发布于 2021-02-04 17:02:51

我曾经遇到过类似的挑战,所以在进行了一些研究并找到了这个回答之后,我使用PostgreSQL触发器实现了一个项目的解决方案。

因此,您可以添加一个触发器,在更新时,它应该移动buttonOrder

下面是我所使用的SQL,这是测试代码,我用regex替换了条件,以适应您的问题:)

代码语言:javascript
复制
    // 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()`);
票数 1
EN

Stack Overflow用户

发布于 2021-02-03 20:31:34

我们提出的一个选项是将订单添加到表单表中。

代码语言:javascript
复制
keystone.createList(
    'forms',
    {
      fields: {
        name: {
          type: Text,
          isRequired: true,
        },
        buttonOrder: {
          type: Text,
        },
        buttons: {
          type: Relationship,
          ref: 'buttons.attached_forms',
          many: true,
        },
      },
    }
);

这个新字段buttonOrder可以包含按钮in顺序的字符串表示形式,就像JSON字符串化数组中的那样。这方面的主要问题是,很难使该字段与实际的链接按钮保持同步。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66034621

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档