Dave Borowitz | 8cdc76b | 2018-03-26 10:04:27 -0400 | [diff] [blame] | 1 | /** |
| 2 | * @license |
| 3 | * Copyright (C) 2017 The Android Open Source Project |
| 4 | * |
| 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | * you may not use this file except in compliance with the License. |
| 7 | * You may obtain a copy of the License at |
| 8 | * |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | * |
| 11 | * Unless required by applicable law or agreed to in writing, software |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | * See the License for the specific language governing permissions and |
| 15 | * limitations under the License. |
| 16 | */ |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 17 | import '@polymer/iron-input/iron-input'; |
| 18 | import '@polymer/iron-icon/iron-icon'; |
| 19 | import '../../../styles/shared-styles'; |
| 20 | import '../gr-button/gr-button'; |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 21 | import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin'; |
| 22 | import {PolymerElement} from '@polymer/polymer/polymer-element'; |
| 23 | import {htmlTemplate} from './gr-list-view_html'; |
| 24 | import {encodeURL, getBaseUrl} from '../../../utils/url-util'; |
| 25 | import {page} from '../../../utils/page-wrapper-utils'; |
Milutin Kristofic | 332cfbf | 2020-11-18 16:41:49 +0100 | [diff] [blame] | 26 | import {property, customElement} from '@polymer/decorators'; |
Ben Rohlfs | e07f818 | 2020-12-07 10:09:20 +0100 | [diff] [blame] | 27 | import {fireEvent} from '../../../utils/event-util'; |
Becky Siegel | 56fbb55 | 2017-06-05 11:18:41 -0700 | [diff] [blame] | 28 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 29 | const REQUEST_DEBOUNCE_INTERVAL_MS = 200; |
Becky Siegel | 56fbb55 | 2017-06-05 11:18:41 -0700 | [diff] [blame] | 30 | |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 31 | declare global { |
| 32 | interface HTMLElementTagNameMap { |
| 33 | 'gr-list-view': GrListView; |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 34 | } |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 35 | } |
| 36 | |
Ben Rohlfs | 04fc1ca | 2021-02-13 13:06:53 +0100 | [diff] [blame] | 37 | const DEBOUNCER_RELOAD = 'reload'; |
| 38 | |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 39 | @customElement('gr-list-view') |
Ben Rohlfs | d94011e | 2021-03-08 23:37:58 +0100 | [diff] [blame] | 40 | class GrListView extends LegacyElementMixin(PolymerElement) { |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 41 | static get template() { |
| 42 | return htmlTemplate; |
| 43 | } |
| 44 | |
| 45 | @property({type: Boolean}) |
| 46 | createNew?: boolean; |
| 47 | |
| 48 | @property({type: Array}) |
| 49 | items?: unknown[]; |
| 50 | |
| 51 | @property({type: Number}) |
| 52 | itemsPerPage = 25; |
| 53 | |
Milutin Kristofic | 332cfbf | 2020-11-18 16:41:49 +0100 | [diff] [blame] | 54 | @property({type: String, observer: '_filterChanged'}) |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 55 | filter?: string; |
| 56 | |
| 57 | @property({type: Number}) |
| 58 | offset?: number; |
| 59 | |
| 60 | @property({type: Boolean}) |
| 61 | loading?: boolean; |
| 62 | |
| 63 | @property({type: String}) |
| 64 | path?: string; |
Dmitrii Filippov | 3fd2b10 | 2019-11-15 16:16:46 +0100 | [diff] [blame] | 65 | |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 66 | /** @override */ |
| 67 | detached() { |
| 68 | super.detached(); |
Ben Rohlfs | 04fc1ca | 2021-02-13 13:06:53 +0100 | [diff] [blame] | 69 | this.cancelDebouncer(DEBOUNCER_RELOAD); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 70 | } |
| 71 | |
Milutin Kristofic | 332cfbf | 2020-11-18 16:41:49 +0100 | [diff] [blame] | 72 | _filterChanged(newFilter?: string, oldFilter?: string) { |
| 73 | // newFilter can be empty string and then !newFilter === true |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 74 | if (!newFilter && !oldFilter) { |
| 75 | return; |
| 76 | } |
| 77 | |
| 78 | this._debounceReload(newFilter); |
| 79 | } |
| 80 | |
Milutin Kristofic | 332cfbf | 2020-11-18 16:41:49 +0100 | [diff] [blame] | 81 | _debounceReload(filter?: string) { |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 82 | this.debounce( |
Ben Rohlfs | 04fc1ca | 2021-02-13 13:06:53 +0100 | [diff] [blame] | 83 | DEBOUNCER_RELOAD, |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 84 | () => { |
| 85 | if (this.path) { |
| 86 | if (filter) { |
| 87 | return page.show( |
| 88 | `${this.path}/q/filter:` + encodeURL(filter, false) |
| 89 | ); |
| 90 | } |
| 91 | return page.show(this.path); |
| 92 | } |
| 93 | }, |
| 94 | REQUEST_DEBOUNCE_INTERVAL_MS |
| 95 | ); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | _createNewItem() { |
Ben Rohlfs | e07f818 | 2020-12-07 10:09:20 +0100 | [diff] [blame] | 99 | fireEvent(this, 'create-clicked'); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 100 | } |
| 101 | |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 102 | _computeNavLink( |
| 103 | offset: number, |
| 104 | direction: number, |
| 105 | itemsPerPage: number, |
| 106 | filter: string, |
| 107 | path: string |
| 108 | ) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 109 | // Offset could be a string when passed from the router. |
| 110 | offset = +(offset || 0); |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 111 | const newOffset = Math.max(0, offset + itemsPerPage * direction); |
Dmitrii Filippov | 0049afe | 2020-07-08 14:08:17 +0200 | [diff] [blame] | 112 | let href = getBaseUrl() + path; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 113 | if (filter) { |
Dmitrii Filippov | e3c09ae | 2020-07-10 11:39:50 +0200 | [diff] [blame] | 114 | href += '/q/filter:' + encodeURL(filter, false); |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 115 | } |
| 116 | if (newOffset > 0) { |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 117 | href += `,${newOffset}`; |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 118 | } |
| 119 | return href; |
| 120 | } |
| 121 | |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 122 | _computeCreateClass(createNew?: boolean) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 123 | return createNew ? 'show' : ''; |
| 124 | } |
| 125 | |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 126 | _hidePrevArrow(loading?: boolean, offset?: number) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 127 | return loading || offset === 0; |
| 128 | } |
| 129 | |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 130 | _hideNextArrow(loading?: boolean, items?: unknown[]) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 131 | if (loading || !items || !items.length) { |
| 132 | return true; |
| 133 | } |
| 134 | const lastPage = items.length < this.itemsPerPage + 1; |
| 135 | return lastPage; |
| 136 | } |
| 137 | |
| 138 | // TODO: fix offset (including itemsPerPage) |
| 139 | // to either support a decimal or make it go to the nearest |
| 140 | // whole number (e.g 3). |
Milutin Kristofic | 848f16c | 2020-08-13 14:25:41 +0200 | [diff] [blame] | 141 | _computePage(offset: number, itemsPerPage: number) { |
Dmitrii Filippov | daf0ec9 | 2020-03-17 11:27:28 +0100 | [diff] [blame] | 142 | return offset / itemsPerPage + 1; |
| 143 | } |
| 144 | } |