blob: c37eb425dfbfc97df67cff7a4c2fda307c38afaa [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import {ChopsAutocomplete} from
6 'elements/chops/chops-autocomplete/chops-autocomplete';
7import {connectStore} from 'reducers/base.js';
8import * as userV0 from 'reducers/userV0.js';
9import * as projectV0 from 'reducers/projectV0.js';
10import {arrayDifference} from 'shared/helpers.js';
11import {userRefsToDisplayNames} from 'shared/convertersV0.js';
12
13
14/**
15 * `<mr-autocomplete>` displays an autocomplete input.
16 *
17 */
18export class MrAutocomplete extends connectStore(ChopsAutocomplete) {
19 /** @override */
20 static get properties() {
21 return {
22 ...ChopsAutocomplete.properties,
23 /**
24 * String for the name of autocomplete vocabulary used.
25 * Valid values:
26 * - 'project': Names of projects available to the current user.
27 * - 'member': All members in the current project a user is viewing.
28 * - 'owner': Similar to member, except with groups excluded.
29 *
30 * TODO(zhangtiff): Implement the following stores.
31 * - 'component': All components in the current project.
32 * - 'label': Well-known labels in the current project.
33 */
34 vocabularyName: {type: String},
35 /**
36 * Object where the keys are 'type' values and each value is an object
37 * with the format {strings, docDict, replacer}.
38 */
39 vocabularies: {type: Object},
40 };
41 }
42
43 /** @override */
44 constructor() {
45 super();
46 this.vocabularyName = '';
47 this.vocabularies = {};
48 }
49
50 /** @override */
51 stateChanged(state) {
52 const visibleMembers = projectV0.viewedVisibleMembers(state);
53 const userProjects = userV0.projects(state);
54 this.vocabularies = {
55 'project': this._setupProjectVocabulary(userProjects),
56 'member': this._setupMemberVocabulary(visibleMembers),
57 'owner': this._setupOwnerVocabulary(visibleMembers),
58 };
59 }
60
61 // TODO(zhangtiff): Move this logic into selectors to prevent computing
62 // vocabularies for every single instance of autocomplete.
63 _setupProjectVocabulary(userProjects) {
64 const {ownerOf = [], memberOf = [], contributorTo = []} = userProjects;
65 const strings = [...ownerOf, ...memberOf, ...contributorTo];
66 return {strings};
67 }
68
69 _setupMemberVocabulary(visibleMembers) {
70 const {userRefs = []} = visibleMembers;
71 return {strings: userRefsToDisplayNames(userRefs)};
72 }
73
74 _setupOwnerVocabulary(visibleMembers) {
75 const {userRefs = [], groupRefs = []} = visibleMembers;
76 const groups = userRefsToDisplayNames(groupRefs);
77 const users = userRefsToDisplayNames(userRefs);
78
79 // Remove groups from the list of all members.
80 const owners = arrayDifference(users, groups);
81 return {strings: owners};
82 }
83
84 /** @override */
85 update(changedProperties) {
86 if (changedProperties.has('vocabularyName') ||
87 changedProperties.has('vocabularies')) {
88 if (this.vocabularyName in this.vocabularies) {
89 const props = this.vocabularies[this.vocabularyName];
90
91 this.strings = props.strings || [];
92 this.docDict = props.docDict || {};
93 this.replacer = props.replacer;
94 } else {
95 // Clear autocomplete if there's no data for it.
96 this.strings = [];
97 this.docDict = {};
98 this.replacer = null;
99 }
100 }
101
102 super.update(changedProperties);
103 }
104}
105customElements.define('mr-autocomplete', MrAutocomplete);