ui: domain_group management

This commit is contained in:
undefined committed 2022-01-12 15:44:58 +08:00
1 parent 8144e85c14
commit b1c63ddd6c
17 files changed
+270 -58

No files matched your search

@@ -23,16 +23,24 @@ function monitorResource(resource) {
export default class DOMAttachedObject {
static uniqueIdCounter = 0;
static DOMAttachKey: string;
static DOMAttachSelector: string;
static DOMDetachSelector: string;
// FIXME should be JQuery<HTMLElement>, but typings for $.transition() wasn't found
$dom: any;
id: number;
detached: boolean;
eventNS: string;
static get($obj) {
const key = this.DOMAttachKey;
return $obj.data(key);
}
static getOrConstruct($obj, ...args) {
static getOrConstruct<T = DOMAttachedObject>($obj, ...args): T {
const $singleObj = $obj.eq(0);
const key = this.DOMAttachKey;
const Protoclass = this;
const Protoclass = this as any;
const instance = this.get($singleObj);
if (instance !== undefined) return instance;
const newInstance = new Protoclass($singleObj, ...args);
@@ -43,7 +51,7 @@ export default class DOMAttachedObject {
return newInstance;
}
static attachAll(container = document.body, ...args) {
static attachAll(container: Document | HTMLElement = document.body, ...args) {
if (process.env.NODE_ENV !== 'production') {
if (!this.DOMAttachSelector) {
// eslint-disable-next-line quotes
@@ -63,7 +71,7 @@ export default class DOMAttachedObject {
}
}
static detachAll(container = document.body) {
static detachAll(container: Document | HTMLElement = document.body) {
const selector = this.DOMDetachSelector || this.DOMAttachSelector;
if (process.env.NODE_ENV !== 'production') {
if (!selector) {
@@ -104,13 +112,13 @@ export default class DOMAttachedObject {
}
detach() {
if (this.constructor.DOMAttachKey) {
this.$dom.removeData(this.constructor.DOMAttachKey);
if ((this.constructor as any).DOMAttachKey) {
this.$dom.removeData((this.constructor as any).DOMAttachKey);
}
this.detached = true;
}
constructor($dom, monitorDetach = false) {
constructor($dom: JQuery<HTMLElement>, monitorDetach = false) {
if ($dom == null) return null;
this.$dom = $dom;
this.id = ++DOMAttachedObject.uniqueIdCounter;
@@ -3,31 +3,31 @@ import ReactDOM from 'react-dom';
import { QueryClient, QueryClientProvider } from 'react-query';
import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoComplete from '.';
import AutoComplete, { AutoCompleteOptions } from '.';
import UserSelectAutoCompleteFC from './components/UserSelectAutoComplete';
export default class UserSelectAutoComplete extends AutoComplete {
export default class UserSelectAutoComplete<Multi extends boolean> extends AutoComplete {
static DOMAttachKey = 'ucwUserSelectAutoCompleteInstance';
client = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
retry: false,
staleTime: Infinity,
},
},
});
constructor($dom, options) {
constructor($dom, options: AutoCompleteOptions<Multi>) {
super($dom, {
classes: 'user-select',
...options,
});
this.client = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
retry: false,
staleTime: Infinity,
},
},
});
}
value() {
value(): Multi extends true ? number[] : string {
if (this.options.multi) return this.ref?.getSelectedItems().map((item) => item._id) ?? this.$dom.val();
return this.ref?.getSelectedItems()[0] ?? null;
}
@@ -5,30 +5,18 @@ import { useQuery } from 'react-query';
import PropTypes from 'prop-types';
import api, { gql } from 'vj/utils/api';
import AutoComplete from './AutoComplete';
interface UserSelectAutoCompleteProps {
multi?: boolean;
defaultItems?: string;
width: string,
height: string,
listStyle: any,
onChange: (value) => any,
allowEmptyQuery: boolean,
freeSolo: boolean,
freeSoloConverter: any,
}
import type { AutoCompleteOptions } from '..';
// eslint-disable-next-line prefer-arrow-callback
const UserSelectAutoComplete = forwardRef(function UserSelectAutoComplete(
props: UserSelectAutoCompleteProps, ref: React.ForwardedRef<AutoComplete>,
props: AutoCompleteOptions, ref: React.ForwardedRef<AutoComplete>,
) {
const multi = props.multi ?? false;
const rawDefaultItems = props.defaultItems ?? '';
const defaultItems = multi ? rawDefaultItems
.split(',')
.map((i) => i.trim())
.filter((i) => i.length)
.map((i) => +i) : rawDefaultItems;
.map((i) => +i.trim())
.filter((i) => i) : rawDefaultItems;
const comRef = useRef<AutoComplete>();
const itemsBox = useRef([]);
@@ -4,8 +4,29 @@ import { assign } from 'lodash';
import DOMAttachedObject from 'vj/components/DOMAttachedObject';
import AutoCompleteFC from './components/AutoComplete';
export interface AutoCompleteOptions<Multi extends boolean = boolean> {
multi?: Multi;
defaultItems?: string;
width?: string;
height?: string;
listStyle?: any;
allowEmptyQuery?: boolean;
freeSolo?: boolean;
freeSoloConverter?: any;
onChange?: (value) => any;
items?: () => Promise<any[]>;
render?: () => string;
text?: () => string;
}
export default class AutoComplete extends DOMAttachedObject {
static DOMAttachKey = 'ucwAutoCompleteInstance';
ref = null;
container = document.createElement('div');
options: AutoCompleteOptions;
changeListener = [
(val) => this.$dom.val(val),
];
constructor($dom, options = {}) {
super($dom);
@@ -16,7 +37,6 @@ export default class AutoComplete extends DOMAttachedObject {
multi: false,
...options,
};
this.ref = null;
this.clear = this.clear.bind(this);
this.onChange = this.onChange.bind(this);
this.attach = this.attach.bind(this);
@@ -25,7 +45,6 @@ export default class AutoComplete extends DOMAttachedObject {
this.value = this.value.bind(this);
this.detach = this.detach.bind(this);
this.focus = this.focus.bind(this);
this.container = document.createElement('div');
this.$dom.addClass('autocomplete-dummy').after(this.container);
// Note: use `setTimeout(fn, 0)` to ensure that code is executed after browser autofill
// also see https://stackoverflow.com/a/779785/13553984
@@ -38,8 +57,9 @@ export default class AutoComplete extends DOMAttachedObject {
else this.ref.closeList();
}
onChange(val) {
this.$dom.val(val);
onChange(val: string | ((v: string) => any)) {
if (typeof val === 'string') this.changeListener.forEach((f) => f(val));
else this.changeListener.push(val);
}
attach() {
@@ -70,7 +90,7 @@ export default class AutoComplete extends DOMAttachedObject {
this.ref.closeList();
}
value() {
value(): any {
if (this.options.multi) return this.$dom.val();
return this.ref?.getSelectedItems()[0] ?? null;
}
@@ -4,7 +4,7 @@ import zIndexManager from 'vj/utils/zIndexManager';
export interface DialogOptions {
classes: string;
$body: HTMLElement;
$body: HTMLElement | JQuery<HTMLElement> | string;
$action: any;
width?: string;
height?: string;
@@ -83,6 +83,11 @@ export class ActionDialog extends Dialog {
...options,
});
}
clear() {
this.$dom.find('input').val('');
return this;
}
}
export class ConfirmDialog extends Dialog {