Skip to content

Commit

Permalink
feat: new util isPrefixName, update form availability
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenesius committed Aug 6, 2023
1 parent d0fabdd commit 9371cf7
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 28 deletions.
156 changes: 155 additions & 1 deletion src/classes/Form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import checkNameInObject from "../utils/check-name-in-object";
import insertByName from "../utils/insert-by-name";
import recursiveRemoveProp from "../utils/recursive-remove-prop";
import runPromiseQueue from "../utils/run-promise-queue";
import isPrefixName from "../utils/is-prefix-name";
import findNearestNameFromArray from "../utils/find-nearest-name-from-array";

/**
* Main principe : GMN
Expand Down Expand Up @@ -362,7 +364,7 @@ export default class Form extends EventEmitter implements FormDependence {
dep?.dispatchEvent(CompareEvent.restoreByName(event, dep.name));
}
})

// Проходим по всем изменениям и уведомляем их
event.comparison.forEach(item => {
console.log(`[%c${this.name}%c] Emit new value event to %c${item.name}`, 'color: red', 'color: black', 'color: red');
this.emit(Form.getEventValueByName(item.name), item.newValue);
Expand Down Expand Up @@ -531,6 +533,158 @@ export default class Form extends EventEmitter implements FormDependence {
}


/**
* @description If true - all elements by default will be blocked.
*/
#disabled: boolean = false;
/**
* @description The Boolean disabled attribute, when present, makes the element not mutable, focusable,
* or even submitted with the form.
* @return {Boolean} isDisabled
* */
get disabled() {
console.log( this.events)
return this.#disabled;
}
/**
* @description Setter for toggle disabled prop. Current function will update disabled state of children elements.
* */
/*
set disabled(value: boolean){
this.#disabled = value;
this.emit(Form.EVENT_UPDATE_ABILITY, this.#disabled);
this.abilities = this.getProxyAbilities();
if (value)
this.disableChildren()
else
this.enableChildren()
}
enable(names?: string | string[]) {
debug.msg(`Enabling ${names || ''}`);
if (typeof names === "string") names = [names];
this.emit(Form.EVENT_ENABLE, names);
if (!names) return this.disabled = false;
names.forEach(name => this.enableByName(name)) ;
}
*/
/**
* @description Вернёт true, если переданное поле является disabled.
* */
/*
checkFieldDisable(fieldName: string): boolean {
const nearestName = findNearestNameFromArray(name, Object.keys(this.abilities));
if (!nearestName) return this.disabled;
return !this.abilities[nearestName];
}
*/
set disabled(v: boolean) {
this.#disabled = v;
}
private getAvailableEventName(fieldName: string) {
return `available:${fieldName}`
}
onavailable(fieldName: string, callback: (disabled: boolean) => any) {
return this.on(this.getAvailableEventName(fieldName), callback);
}
disable(names?: string | string[]){
debug.msg(`Disabling ${names || ''}`);
this.available(false, names)
}
enable(names?: string | string[]) {
debug.msg(`Enabling ${names || ''}`);
this.available(true, names)
}
available(type: boolean, names?: string[] | string ) {
console.group(`AVAILABLE %c${type}`, 'color: purple')
if (typeof names === "string") names = [names];
if (!names) return this.disabled = type;

// Чистка от бессмысленных полей. Если указаны address и address.name, то второй не имеет нагрузку, т.к. address
// и так будет полностью блокировать/разблокировать поля.
// Массив будет содержать только те поля, в блокировки которых есть смысл, и не присуще повторения.
let nameState: string[] = []
names.forEach(fieldName => {
// Если уже в сохранённых именах есть имя, которое является родительским для текущего. В таком случае
// нет смысла добавлять текущее, т.к. оно и так будет замещено.
if (nameState.find(name => isPrefixName(fieldName, name))) return;

// Убираем ранее добавленные поля, но которые на данном шаге потеряли смысл, т.к. текущее поле является для
// них родительским.
nameState = nameState.filter(name => !isPrefixName(name, fieldName));
nameState.push(fieldName)
})

const av = {
"address": false,
"address.city": true,
"address.city.type": false,
"address.city.type.index": true,
"name": false,
"user": false,
"user.application": true,
"user.customer.id": true
}

console.log(nameState, type, av);

const changes: any = []

nameState.forEach(name => {
let _stateNames = Object.keys(av) as (keyof typeof av)[];

console.group(`Update for ${name}`);

const fieldForUpdate = [];

// Если Disable, и такого поля у нас нет - добавляем его
if (type === false && !Object.prototype.hasOwnProperty.call(av, name)) {

const nearestName = findNearestNameFromArray(name, _stateNames)

if (!nearestName || av[nearestName] !== type) fieldForUpdate.push(name)
}

fieldForUpdate.push(
..._stateNames.filter((key => (isPrefixName(key, name) || key === name) && (av[key] !== type)))
)
console.log(fieldForUpdate)
console.groupEnd()
})



// names.forEach(name => this.availableByName(name, type)) ;
console.groupEnd();
}

#abilities: Record<string, boolean> = {}
/**
* @description Метод должен обработать fieldName, и пройтись по вложенностям и
* */
availableByName(fieldName: string, available: boolean) {
const parsedName = splitName(fieldName);

function set(n: string, v: boolean) {
console.log('')
}

for(let index = 0; index < parsedName.length; index ++) {
const searchName = concatName(...parsedName.slice(0, parsedName.length - index));

if (this.#abilities.hasOwnProperty(searchName)) {
if (this.#abilities[searchName] !== available) set(searchName, available)
break;
}
}

}
}

interface FormParams {
Expand Down
8 changes: 4 additions & 4 deletions src/utils/find-nearest-name-from-array.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import checkCompositeName from "./check-composite-name";

export default function findNearestNameFromArray(name: string, array: string[]): string | undefined {
let answer = "";
export default function findNearestNameFromArray<T extends string>(name: string, array: T[]): T | undefined {
let answer: T | undefined;

array.forEach(n => {

if (!checkCompositeName(n, name)) return;
if (n.length > answer.length) answer = n;
if (n.length > (answer?.length || 0)) answer = n;
})

return answer.length === 0 ? undefined: answer
return answer?.length ? answer : undefined
}
9 changes: 9 additions & 0 deletions src/utils/is-prefix-name.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* @description Return true if the prefix is some parent of provided field name.
* @example address.city.name address -> true
* @example user.type.index user.type -> true
* @example position.city.type city -> false
* */
export default function isPrefixName(fieldName: string, prefix: string) {
return (new RegExp(`^${prefix}\.`)).test(fieldName);
}
22 changes: 0 additions & 22 deletions tests/form/form-disable.spec.ts

This file was deleted.

34 changes: 34 additions & 0 deletions tests/units/form/form-disable.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import Form from "../../../src/classes/Form";

describe("Test for check disabled/enabled state", () => {
/*
it('should be enable by default', function () {
const form = new Form();
expect(form.disabled).toBe(false)
});
it('should be disabled = true, after invoke form.disable', function () {
const form = new Form()
form.disable();
expect(form.disabled).toBe(true)
});
it('should be disabled = false, after invoke disable and then enable', function () {
const form = new Form()
form.disable();
form.enable();
expect(form.disabled).toBe(false)
});
it("should disabled just one field, not full form", () => {})
it("Field should be disable if parent is disabled", () => {})
it("Field should be enable if grandparent is disabled, but parent is enable", () => {})
it("Should disabled in child", () => {})
it("Should enable in child", () => {})
it("Disable full form", () => {})
it("Enable full form", () => {})
it("Disable child form", () => {})
it("Enable child form", () => {})
it("Field should be enable in child form.", () => {})
it("Field should be disable in child form.", () => {});
it("Enable parent form should clean all disable fields", () => {})
*/
})
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import findNearestNameFromArray
from "../../plugin/utils/find-nearest-name-from-array";
from "../../../src/utils/find-nearest-name-from-array";

describe("Nearest name", () => {

Expand Down
13 changes: 13 additions & 0 deletions tests/units/utils/is-prefix-name.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import isPrefixName from "./../../../src/utils/is-prefix-name";

describe("Is prefix name", () => {
test("Simple name", () => {
expect(isPrefixName("address.city.name", "address")).toBe(true)
})
test("Multi name name", () => {
expect(isPrefixName("user.type.index", "user.type")).toBe(true)
})
test("Should return false if second param is not prefix", () => {
expect(isPrefixName("position.city.type", "city")).toBe(false)
})
})

0 comments on commit 9371cf7

Please sign in to comment.