208 lines
6.4 KiB
TypeScript
208 lines
6.4 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
import '@polymer/iron-input/iron-input';
|
|
import '@polymer/paper-toggle-button/paper-toggle-button';
|
|
import '../../../styles/gr-form-styles';
|
|
import '../../../styles/gr-subpage-styles';
|
|
import '../../../styles/shared-styles';
|
|
import '../../shared/gr-icons/gr-icons';
|
|
import '../../shared/gr-select/gr-select';
|
|
import '../../shared/gr-tooltip-content/gr-tooltip-content';
|
|
import '../gr-plugin-config-array-editor/gr-plugin-config-array-editor';
|
|
import {dom, EventApi} from '@polymer/polymer/lib/legacy/polymer.dom';
|
|
import {GestureEventListeners} from '@polymer/polymer/lib/mixins/gesture-event-listeners';
|
|
import {LegacyElementMixin} from '@polymer/polymer/lib/legacy/legacy-element-mixin';
|
|
import {PolymerElement} from '@polymer/polymer/polymer-element';
|
|
import {htmlTemplate} from './gr-repo-plugin-config_html';
|
|
import {customElement, property} from '@polymer/decorators';
|
|
import {ConfigParameterInfoType} from '../../../constants/constants';
|
|
import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces';
|
|
import {
|
|
ConfigParameterInfo,
|
|
PluginParameterToConfigParameterInfoMap,
|
|
} from '../../../types/common';
|
|
import {PaperToggleButtonElement} from '@polymer/paper-toggle-button/paper-toggle-button';
|
|
import {IronInputElement} from '@polymer/iron-input/iron-input';
|
|
import {
|
|
PluginConfigOptionsChangedEventDetail,
|
|
PluginOption,
|
|
} from './gr-repo-plugin-config-types';
|
|
|
|
const PLUGIN_CONFIG_CHANGED_EVENT_NAME = 'plugin-config-changed';
|
|
|
|
export interface ConfigChangeInfo {
|
|
_key: string; // parameterName of PluginParameterToConfigParameterInfoMap
|
|
info: ConfigParameterInfo;
|
|
notifyPath: string;
|
|
}
|
|
|
|
export interface PluginData {
|
|
name: string; // parameterName of PluginParameterToConfigParameterInfoMap
|
|
config: PluginParameterToConfigParameterInfoMap;
|
|
}
|
|
|
|
export interface PluginConfigChangeDetail {
|
|
name: string; // parameterName of PluginParameterToConfigParameterInfoMap
|
|
config: PluginParameterToConfigParameterInfoMap;
|
|
notifyPath: string;
|
|
}
|
|
|
|
@customElement('gr-repo-plugin-config')
|
|
class GrRepoPluginConfig extends GestureEventListeners(
|
|
LegacyElementMixin(PolymerElement)
|
|
) {
|
|
static get template() {
|
|
return htmlTemplate;
|
|
}
|
|
|
|
/**
|
|
* Fired when the plugin config changes.
|
|
*
|
|
* @event plugin-config-changed
|
|
*/
|
|
|
|
@property({type: Object})
|
|
pluginData?: PluginData;
|
|
|
|
@property({
|
|
type: Array,
|
|
computed: '_computePluginConfigOptions(pluginData.*)',
|
|
})
|
|
_pluginConfigOptions!: PluginOption[]; // _computePluginConfigOptions never returns null
|
|
|
|
_computePluginConfigOptions(
|
|
dataRecord: PolymerDeepPropertyChange<PluginData, PluginData>
|
|
): PluginOption[] {
|
|
if (!dataRecord || !dataRecord.base || !dataRecord.base.config) {
|
|
return [];
|
|
}
|
|
const config = dataRecord.base.config;
|
|
return Object.keys(config).map(_key => {
|
|
return {_key, info: config[_key]};
|
|
});
|
|
}
|
|
|
|
_isArray(type: ConfigParameterInfoType) {
|
|
return type === ConfigParameterInfoType.ARRAY;
|
|
}
|
|
|
|
_isBoolean(type: ConfigParameterInfoType) {
|
|
return type === ConfigParameterInfoType.BOOLEAN;
|
|
}
|
|
|
|
_isList(type: ConfigParameterInfoType) {
|
|
return type === ConfigParameterInfoType.LIST;
|
|
}
|
|
|
|
_isString(type: ConfigParameterInfoType) {
|
|
// Treat numbers like strings for simplicity.
|
|
return (
|
|
type === ConfigParameterInfoType.STRING ||
|
|
type === ConfigParameterInfoType.INT ||
|
|
type === ConfigParameterInfoType.LONG
|
|
);
|
|
}
|
|
|
|
_computeDisabled(editable: string) {
|
|
return editable === 'false';
|
|
}
|
|
|
|
_computeChecked(value = 'false') {
|
|
return JSON.parse(value) as boolean;
|
|
}
|
|
|
|
_handleStringChange(e: Event) {
|
|
const el = (dom(e) as EventApi).localTarget as IronInputElement;
|
|
// In the template, the data-option-key is assigned to each editor
|
|
const _key = el.getAttribute('data-option-key')!;
|
|
const configChangeInfo = this._buildConfigChangeInfo(el.value, _key);
|
|
this._handleChange(configChangeInfo);
|
|
}
|
|
|
|
_handleListChange(e: Event) {
|
|
const el = (dom(e) as EventApi).localTarget as HTMLOptionElement;
|
|
// In the template, the data-option-key is assigned to each editor
|
|
const _key = el.getAttribute('data-option-key')!;
|
|
const configChangeInfo = this._buildConfigChangeInfo(el.value, _key);
|
|
this._handleChange(configChangeInfo);
|
|
}
|
|
|
|
_handleBooleanChange(e: Event) {
|
|
const el = (dom(e) as EventApi).localTarget as PaperToggleButtonElement;
|
|
// In the template, the data-option-key is assigned to each editor
|
|
const _key = el.getAttribute('data-option-key')!;
|
|
const configChangeInfo = this._buildConfigChangeInfo(
|
|
JSON.stringify(el.checked),
|
|
_key
|
|
);
|
|
this._handleChange(configChangeInfo);
|
|
}
|
|
|
|
_buildConfigChangeInfo(
|
|
value: string | null | undefined,
|
|
_key: string
|
|
): ConfigChangeInfo {
|
|
// If pluginData is not set, editors are not created and this method
|
|
// can't be called
|
|
const info = this.pluginData!.config[_key];
|
|
info.value = value !== null ? value : undefined;
|
|
return {
|
|
_key,
|
|
info,
|
|
notifyPath: `${_key}.value`,
|
|
};
|
|
}
|
|
|
|
_handleArrayChange(e: CustomEvent<PluginConfigOptionsChangedEventDetail>) {
|
|
this._handleChange(e.detail);
|
|
}
|
|
|
|
_handleChange({_key, info, notifyPath}: ConfigChangeInfo) {
|
|
// If pluginData is not set, editors are not created and this method
|
|
// can't be called
|
|
const {name, config} = this.pluginData!;
|
|
|
|
/** @type {Object} */
|
|
const detail: PluginConfigChangeDetail = {
|
|
name,
|
|
config: {...config, [_key]: info},
|
|
notifyPath: `${name}.${notifyPath}`,
|
|
};
|
|
|
|
this.dispatchEvent(
|
|
new CustomEvent(PLUGIN_CONFIG_CHANGED_EVENT_NAME, {
|
|
detail,
|
|
bubbles: true,
|
|
composed: true,
|
|
})
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Work around a issue on iOS when clicking turns into double tap
|
|
*/
|
|
_onTapPluginBoolean(e: Event) {
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'gr-repo-plugin-config': GrRepoPluginConfig;
|
|
}
|
|
}
|