我如何在Tresorit中实施多项选择

Tresorit has a web application up and running for years now. It contains several views where specific resources are listed (e.g. files, folders, and users). It is possible to perform operations on these resources, however, for power users, it was missing something significant; the ability to select multiple items at the same time and perform batch actions on the selected resources. Luckily, I was given the opportunity to implement this feature while working with a handful of people from UX and Product development teams. I’m going to highlight my biggest learnings from this brief month-long project.

Tresorit的Web应用程序已经运行多年。 它包含几个列出了特定资源(例如文件,文件夹和用户)的视图。 可以在这些资源上执行操作,但是,对于高级用户而言,它缺少一些重要的东西。 同时选择多个项目并对所选资源执行批处理操作的能力。 幸运的是,在与来自UX和产品开发团队的少数人员一起工作的过程中,我获得了实现此功能的机会。 我将重点介绍这个简短的为期一个月的项目所学到的最大知识。

一切如何开始 (How it all began)

Our web-based client is an Angular 7 application which is built in a pretty standard way. Listing pages have wrapper components that contain the list item components. With multiple selection, each list item will have a checkbox. Also, the list header will make it possible to select all displayed items as depicted below.

我们基于Web的客户端是Angular 7应用程序,它以非常标准的方式构建。 列表页面具有包含列表项组件的包装器组件。 选择多项后,每个列表项都会有一个复选框。 同样,列表标题将使您可以选择所有显示的项目,如下所示。

Image for post
Multiple selection in all its glory
荣耀中的多重选择

At the start of the project, I thought the best way would be to create an abstract selection handling pattern that will be reusable for every page. It turned out these expectations weren’t so far fetched, however they were far from reality.

在项目开始时,我认为最好的方法是创建一个抽象选择处理模式,该模式可用于每个页面。 事实证明,这些期望并不是遥不可及的,但是与现实相去甚远。

To avoid the unpleasant case of implementing unnecessary abstraction before any working code, I started to work on a Proof of Concept implementation for one of the most complex pages where two different types of resources are accessible.

为了避免在任何工作代码之前实现不必要的抽象的不愉快情况,我开始为最复杂的页面之一(其中可访问两种不同类型的资源)进行概念验证实现。

I started with implementing a basic Angular service with the following responsibilities:

我从实现具有以下职责的基本Angular服务开始:

  • Store selected list items. (I chose to store the Angular component instances so I can access the already implemented functions if needed.)

    存储选定的列表项。 (我选择存储Angular组件实例,以便在需要时可以访问已实现的功能。)
  • Emit RxJS events for single selection as well as all selection toggles.

    发出RxJS事件以进行单个选择以及所有选择切换。
  • Clear selection when navigation occurs.

    导航时清除选择。
  • Perform batch operations on the selected resources.

    对所选资源执行批处理操作。

List items use the service as follows:

列表项使用该服务的方式如下:

  • On selection toggle, they add (or remove) themselves from the selected items array of the service.

    在选择切换时,它们会从服务的选定项目数组中添加(或删除)自己。
  • Handle the all selection toggle event accordingly.

    相应地处理所有选择切换事件。

Components which contain the select all toggle have slightly more responsibilities than their list-item counterparts:

包含“全选”切换的组件比其列表项对应的组件承担的责任略多:

  • Handle selection change event.

    处理选择更改事件。
  • If every item is selected individually then toggle all selection, same with deselection.

    如果单独选择了每个项目,则切换所有选择,与取消选择相同。
  • Determine available batch operations for selected items.

    确定所选项目的可用批处理操作。
  • Make these operations accessible for the user in the form of a context menu and/or several action buttons.

    通过上下文菜单和/或几个操作按钮的形式使用户可以访问这些操作。

Besides this several UI changes were needed. However, from a technological perspective, these were more straightforward. Half of these additions were CSS changes, but the other half consisted of an insane amount of logic to determine if every visible item got selected and what exactly which batch actions are available for these items. More on that soon.

除此之外,还需要对UI进行一些更改。 但是,从技术角度来看,这些更为简单。 这些添加的一半是CSS更改,但是另一半则由大量逻辑组成,用于确定是否选择了每个可见项目以及这些项目可使用哪些批处理操作。 很快就可以了。

Image for post

完成概念验证 (Finishing the Proof of Concept)

It came clear after encountering the second listing page that a perfect abstraction would be impossible over the project’s time frame for the following reasons:

在遇到第二个列表页面后,很明显,由于以下原因 ,在项目的时间范围内不可能实现完美的抽象

  1. The component hierarchy isn’t the same throughout the listings

    整个清单中的组件层次结构都不相同
  2. The implementation follows different concepts

    实施遵循不同的概念
  3. Inability to use polymorphism due to the lack of OOP in our current implementation

    由于我们当前的实施中缺少OOP,因此无法使用多态
  4. Special cases of list items can occur. (e.g. deleted files, suspended users)

    列表项的特殊情况可能会发生。 (例如,已删除的文件,暂停的用户)

  5. There is no unified data representation

    没有统一的数据表示
  6. Every list item behaves differently

    每个列表项的行为都不同
  7. Most of our flows were implemented for a single item

    我们大多数流程都是针对单个项目实施的

组件层次 (Component hierarchy)

In some cases, the wrapper list component doesn’t contain the all selection toggle. Instead, special list items function as group headers. This introduces the need for more RxJS observables since otherwise it wouldn’t be possible to distinguish which group was selected. This leads to more event handling, Subscriptions, and so on.

在某些情况下,包装器列表组件不包含所有选择切换。 而是,特殊列表项用作组标题。 这引入了对更多RxJS可观察对象的需求,因为否则将无法区分选择了哪个组。 这导致更多的事件处理,订阅等。

不同的实现 (Different implementation)

The problem here is that it’s much more difficult to apply any sort of abstraction when the affected components execute the same logic differently. To spice things up, one particular case is where the user can select all items in subcategories. This isn’t a big deal all by itself, the annoying part for me was the realization that almost none of our listing pages are consistent in the application, which could lead to usability issues as well.

这里的问题是,当受影响的组件以不同的方式执行相同的逻辑时,应用任何种类的抽象要困难得多。 为了增加趣味性,一种特殊情况是用户可以选择子类别中的所有项目。 就其本身而言,这并不是什么大不了的事情,对我而言,令人烦恼的部分是认识到我们的列表页面几乎与应用程序不一致,这也可能导致可用性问题。

缺乏面向对象 (Lack of OOP)

This introduces a simple problem. I had to implement some functions several times with the same responsibilities. I could get into a mad refactoring spree but that could’ve resulted in running out of time and lead to future maintainability questions as well. As we all know, deadlines exist for a reason. However, I took note of these so our team can consider all future improvement possibilities.

这引入了一个简单的问题。 我不得不以相同的职责多次实施某些功能。 我可能会疯狂地疯狂进行重构,但这可能会导致时间用光,并引发未来的可维护性问题。 众所周知,截止日期存在是有原因的。 但是,我注意到了这些,以便我们的团队可以考虑所有未来的改进可能性。

特别清单项目 (Special list items)

Some listing pages contain different toggles that control what kind of list items are displayed. A fine example is “Show deleted” — which makes deleted items appear, thus all selection has to be reevaluated not to mention updating the list has to take this into account as well.

某些列表页面包含不同的切换,用于控制显示哪种列表项。 一个很好的例子是“显示已删除” ,它使已删除的项目出现,因此必须重新评估所有选择,更不用说更新列表了。

仅单项动作 (Only single item actions)

Most of our data manipulating flows contain confirmation modals or some other more complex modals, not to mention event tracking to see a user’s progress in the flow. Several questions arose, some including

我们大多数的数据处理流程都包含确认模式或其他一些更复杂的模式,更不用说事件跟踪来查看用户在流程中的进度。 出现了几个问题,包括

  • Do we want tracking events for every single resource or only one per batch?

    我们要跟踪每个资源的事件还是每个批次一个事件?
  • How do we change tracking parameters to be comprehensible and meaningful?

    我们如何更改跟踪参数以使其易于理解和有意义?
  • How should we show potential errors and warnings to the user during batch actions?

    在批处理操作期间,我们应如何向用户显示潜在的错误和警告?
  • Do we want server endpoints to manipulate resources in a batch instead of an API call for every single item? (The answer was a straight no so far, this was a front-end development project.)

    我们是否希望服务器端点批量处理资源,而不是为每个项目都进行API调用? (到目前为止,答案是直接的,这是一个前端开发项目。)

The first obvious thing, in this case, was that modals have to be able to handle one or more items as input parameters at once.

在这种情况下,第一个显而易见的事情是模态必须能够同时处理一个或多个项目作为输入参数。

解决的办法是妥协 (The solution was to compromise)

Due to the detailed list of interfering factors above I had to compromise.

由于上述干扰因素的详细清单,我不得不妥协。

The selection handler service only handles singular item selections and emits events accordingly. Different selection events (believe me, there are quite a few) are emitted by the respective list wrapper components or group header list items. These additional events are handled accordingly where needed.

选择处理程序服务仅处理单个项目选择,并相应地发出事件。 各个列表包装器组件或组头列表项发出不同的选择事件(相信我,有很多) 。 这些其他事件将在需要时进行相应处理。

I added no abstract Angular components for list items, and list wrappers because I didn’t want to risk adding the possibility of new bugs into the whole application.

我没有为列表项和列表包装添加任何抽象的Angular组件,因为我不想冒险在整个应用程序中添加新错误的可能性。

I didn’t unify the logic for the availability of batch operations. According to the agreed specification:

我没有统一批处理操作的逻辑。 根据约定的规范:

  • If any batch operation is available always show one primary action

    如果有任何批处理操作,请始终显示一项主要操作
  • If only two actions are available show them as action buttons

    如果只有两个动作可用,请将它们显示为动作按钮
  • If more than two actions are available, show one primary action and another button opening a context menu with the remaining actions

    如果有两个以上的操作可用,则显示一个主要操作,另一个按钮打开上下文菜单,其余的操作

This resulted in an insane amount of states and backtracking so that every use-case works as intended, or that one additional case doesn’t mess with the already implemented ones. For example, the code below shows the conditions that have to be met for one button to be visible on our pages.

这导致大量的状态和回溯,以至于每个用例都按预期工作,或者另外一个用例不会与已经实现的用例相混淆。 例如,以下代码显示了在我们的页面上可见一个按钮所必须满足的条件

Note that in some cases almost any option can appear in the context menu or as an action button. However, should something appear as an action button, that option is not accessible from the context menu.

请注意,在某些情况下,几乎任何选项都可以显示在上下文菜单中或作为操作按钮。 但是,如果将某些内容显示为操作按钮,则无法从上下文菜单访问该选项。

Without further explanation, I think it’s obvious to see that these monstrosities took up most of the coding work and testing 😆. I know from a mathematical standpoint that these could have been brought to a simpler form, however, in this form, the predicates translate to specific use-cases which make the code more comprehensible, should modifications be needed in the future.

如果没有进一步的解释,我认为很明显这些怪兽占据了大部分编码工作和测试testing。 从数学的角度来看,我知道可以将它们简化为一个简单的形式,但是在这种形式下,谓词可以转换为特定的用例,以备将来需要修改时使代码更易于理解。

After seeing how wild these conditions can get I added a new service that only contains helper functions to make these conditions shorter and more understandable.

在看到这些条件变得多么疯狂之后,我添加了一个仅包含辅助函数的新服务,以使这些条件更短并且更易于理解。

要点和进一步的改进 (Takeaways and further improvements)

This project was special since it was the first time I had the opportunity to work alone as a developer closely with UX and product management. At first, it seemed a little intimidating, but soon enough fear turned into excitement as I started to embrace the opportunity I was given. Of course, I had the option to consult with my teammates (for which I am thankful), but it was my responsibility to make architectural decisions and move forward with them.

这个项目很特别,因为这是我第一次有机会作为一名独立于UX和产品管理的开发人员一起工作。 起初,这似乎有点令人生畏,但随着我开始接受给我的机会,很快足够的恐惧变成了兴奋。 当然,我可以选择与我的队友协商(对此我很感激) ,但是我有责任做出架构决定并与他们一起前进。

I am glad that everything necessary to consider this project successful got completed more or less in an optimal manner. Of course, I can see areas that can be further improved in the future:

我很高兴认为这个项目成功的所有必要条件或多或少都以最佳的方式完成了。 当然,我可以看到将来可以进一步改进的领域:

  • Event handling tweaks, since some events might get triggered unnecessarily

    事件处理进行了调整,因为某些事件可能会被不必要地触发
  • A more consistent UI

    更加一致的用户界面
  • Improving abstraction and component hierarchy

    改善抽象和组件层次结构

All in all, I’ve learned a lot and it was a great experience and change of pace to be a part of this project.

总而言之,我学到了很多东西,成为这个项目的一部分,这是一次很棒的经历,并且改变了步伐。

翻译自: https://medium.com/tresorit-engineering/how-ive-implemented-multiple-selection-into-tresorit-2ed7f1bff5e0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
92讲视频课+16大项目实战+课件源码  为什么学习数据分析?       人工智能、大数据时代有什么技能是可以运用在各种行业的?数据分析就是。      从海量数据获得别人看不见的信息,创业者可以通过数据分析来优化产品,营销人员可以通过数据分析改进营销策略,产品经理可以通过数据分析洞察用户习惯,金融从业者可以通过数据分析规避投资风险,程序员可以通过数据分析进一步挖掘出数据价值,它和编程一样,本质上也是一个工具,通过数据来对现实事物进行分析和识别的能力。不管你从事什么行业,掌握了数据分析能力,往往在其岗位上更有竞争力。   本课程共包含五大模块: 一、先导篇: 通过分析数据分析师的一天,让学员了解全面了解成为一个数据分析师的所有必修功法,对数据分析师不在迷惑。  二、基础篇: 围绕Python基础语法介绍、数据预处理、数据可视化以及数据分析与挖掘......这些核心技能模块展开,帮助你快速而全面的掌握和了解成为一个数据分析师的所有必修功法。 三、数据采集篇: 通过网络爬虫实战解决数据分析的必经之路:数据从何来的问题,讲解常见的爬虫套路并利用三大实战帮助学员扎实数据采集能力,避免没有数据可分析的尴尬。  四、分析工具篇: 讲解数据分析避不开的科学计算库Numpy、数据分析工具Pandas及常见可视化工具Matplotlib。  五、算法篇: 算法是数据分析的精华,课程精选10大算法,包括分类、聚类、预测3大类型,每个算法都从原理和案例两个角度学习,让你不仅能用起来,了解原理,还能知道为什么这么做。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值