Skip to content

Commit

Permalink
Merge pull request #1945 from ThemeFuse/23522-filtersFromApi
Browse files Browse the repository at this point in the history
Filters From Api
  • Loading branch information
lift46252 authored Oct 19, 2023
2 parents 1a0a2c9 + 64f9bc5 commit d07a0f8
Show file tree
Hide file tree
Showing 8 changed files with 315 additions and 0 deletions.
37 changes: 37 additions & 0 deletions public/editor-client/src/Elements/Filters/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { getFields } from "../../api";
import { Filters } from "../../types/Filters";
import { t } from "../../utils/i18n";
import { converter, parseFields } from "./utils";

export const handler: Filters["handler"] = async (res, rej, data) => {
try {
const result = await getFields(data);

const convertedValue = converter(result);

res(convertedValue ?? []);
} catch (e) {
rej(t("Failed to load sources"));
}
};

export const possibleValues: Filters["possibleValues"] = async (
res,
rej,
{ type, search, optionSource, postId, loopAttributes }
) => {
try {
const result = await getFields({ postId, loopAttributes });

const convertPossibleValues = parseFields(
result,
optionSource,
type,
search
);

res(convertPossibleValues ?? []);
} catch (e) {
rej(t("Failed to load sources"));
}
};
105 changes: 105 additions & 0 deletions public/editor-client/src/Elements/Filters/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
Choice,
FilterFieldsData,
fromStringQueryTypeSource,
isChoiceArray,
isPossibleValueArray,
PossibleValue,
QueryTypeSource
} from "../../types/Filters";
import { isAllValuesValid } from "../../utils/reader/array";

export const createQueryTypeSource = (
query: string,
type: string,
source: string,
filterBy: string
): QueryTypeSource | undefined =>
fromStringQueryTypeSource(`${query}|||${type}|||${source}|||${filterBy}`);

export const converter = (data: FilterFieldsData): Choice[] => {
const arr = Object.values(data).reduce((acc: Choice[], cur) => {
const field = cur.map((item) => {
return {
value:
createQueryTypeSource(
getQuery(item.filterQuery, item.optionQuery, item.optionSource),
item.type,
item.optionSource,
item.filterBy
) ?? "",
title: item.label
};
});
return [...acc, ...field];
}, []);

return arr ?? [];
};

export const getQuery = (
filterQuery: string,
optionQuery: string,
optionSource: string
): string => filterQuery || optionQuery || `metaKey=${optionSource}`;

export const parseFields = (
data: FilterFieldsData,
optionSource: string,
type: string,
search?: string
): Choice[] => {
const allItem = { value: "all", title: type === "inc" ? "All" : "None" };

const selectedItem = Object.values(data).reduce((acc, cur) => {
const field = cur.filter((item) => item.optionQuery === optionSource);

return [...acc, ...field];
}, [])[0];

if (selectedItem.optionSource === "tax") {
const parsedValues: PossibleValue[] = isPossibleValueArray(
selectedItem.possibleValues
)
? selectedItem.possibleValues
: [];
const items: Choice[] = parsedValues.map((it) => ({
value: it.term_id,
title: it.name
}));

if (search) {
return [
allItem,
...items.filter((it) =>
it.title.toLocaleLowerCase().includes(search.toLocaleLowerCase())
)
];
}

if (isAllValuesValid(items)) {
return [allItem, ...items];
}
}

if (selectedItem.optionSource === "meta") {
const items = isChoiceArray(selectedItem.possibleValues)
? selectedItem.possibleValues
: [];

if (search) {
return [
allItem,
...items.filter((it) =>
it.title.toLocaleLowerCase().includes(search.toLocaleLowerCase())
)
];
}

if (isAllValuesValid(items)) {
return [allItem, ...items];
}
}

return [allItem];
};
37 changes: 37 additions & 0 deletions public/editor-client/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -848,3 +848,40 @@ export const updateBlockScreenshot = async ({
};

//#endregion

//#region FiltersFields

export const getFields = async (data: {
postId: string;
loopAttributes: string;
}) => {
try {
const config = getConfig();

if (!config) {
throw new Error(t("Invalid __BRZ_PLUGIN_ENV__"));
}

const { editorVersion, url, hash, actions } = config;

const body = new URLSearchParams({
hash,
version: editorVersion,
action: actions.filterFields,
...data
});

const result = await request(url, {
method: "POST",
body
});

const r = await result.json();

return r.data;
} catch (e) {
throw new Error(t("Fail to load fields!"));
}
};

//#endregion
6 changes: 6 additions & 0 deletions public/editor-client/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ interface Actions {

createBlockScreenshot: string;
updateBlockScreenshot: string;

filterFields: string;
}

interface API {
Expand Down Expand Up @@ -190,6 +192,10 @@ const actionsReader = parseStrict<PLUGIN_ENV["actions"], Actions>({
updateBlockScreenshot: pipe(
mPipe(Obj.readKey("updateBlockScreenshot"), Str.read),
throwOnNullish("Invalid actions: updateBlockScreenshot")
),
filterFields: pipe(
mPipe(Obj.readKey("filterFields"), Str.read),
throwOnNullish("Invalid actions: filterFields")
)
});

Expand Down
13 changes: 13 additions & 0 deletions public/editor-client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
defaultPopups,
defaultStories
} from "./defaultTemplates";
import { handler as filters, possibleValues } from "./Elements/Filters";
import { handler as posts } from "./Elements/Posts";
import { addMedia } from "./media/addMedia";
import { addMediaGallery } from "./media/addMediaGallery";
Expand Down Expand Up @@ -74,7 +75,19 @@ if (window.__VISUAL_CONFIG__) {
// Elements
if (window.__VISUAL_CONFIG__.elements) {
set(window.__VISUAL_CONFIG__.elements, ["posts", "handler"], posts);
set(window.__VISUAL_CONFIG__.elements, ["filters", "handler"], filters);
set(
window.__VISUAL_CONFIG__.elements,
["filters", "possibleValues"],
possibleValues
);
} else {
set(window.__VISUAL_CONFIG__, ["elements", "posts", "handler"], posts);
set(window.__VISUAL_CONFIG__, ["elements", "filters", "handler"], filters);
set(
window.__VISUAL_CONFIG__,
["elements", "filters", "possibleValues"],
possibleValues
);
}
}
112 changes: 112 additions & 0 deletions public/editor-client/src/types/Filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { pass } from "fp-utilities";
import { Literal } from "../utils/types";
import { NewType } from "./NewType";
import { Response } from "./Response";

export type Choice = { title: string; value: Literal };

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isChoice = (values: any): values is Choice => {
return typeof values === "object" && "title" in values && "value" in values;
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isChoiceArray = (arr: any): arr is Choice[] => {
if (!Array.isArray(arr)) return false;
for (const item of arr) {
if (!isChoice(item)) return false;
}
return true;
};

export type QueryTypeSource = NewType<string, "tripleString">;

export const isQueryTypeSource = (s: string): s is QueryTypeSource =>
s.split("|||").length === 3;

export const fromStringQueryTypeSource = pass(isQueryTypeSource);

interface FieldsCommon {
filterQuery: string;
label: string;
optionQuery: string;
optionSource: string;
filterBy: string;
type: string;
}

export interface FilterField extends FieldsCommon {
possibleValues: PossibleValue[] | Choice[];
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isPossibleValue = (values: any): values is PossibleValue => {
return (
typeof values === "object" &&
"count" in values &&
"description" in values &&
"filter" in values &&
"name" in values &&
"parent" in values &&
"slug" in values &&
"taxonomy" in values &&
"term_group" in values &&
"term_id" in values &&
"term_taxonomy_id" in values
);
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isPossibleValueArray = (arr: any): arr is PossibleValue[] => {
if (!Array.isArray(arr)) return false;
for (const item of arr) {
if (!isPossibleValue(item)) return false;
}
return true;
};

export type PossibleValue = {
count: number;
description: string;
filter: string;
name: string;
parent: number;
slug: string;
taxonomy: string;
term_group: number;
term_id: number;
term_taxonomy_id: number;
};

export type FilterFieldsData = {
fields: FilterField[];
taxonomies: FilterField[];
metaFields: FilterField[];
authors: FilterField[];
};

export interface FiltersHandlerArgs {
postId: string;
loopAttributes: string;
}

export interface FiltersValuesArgs {
postId: string;
loopAttributes: string;
optionSource: string;
type: string;
search?: string;
}

export interface Filters {
handler: (
res: Response<Choice[]>,
rej: Response<string>,
args: FiltersHandlerArgs
) => void;
possibleValues: (
res: Response<Choice[]>,
rej: Response<string>,
data: FiltersValuesArgs
) => void;
}
2 changes: 2 additions & 0 deletions public/editor-client/src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { AddMediaData, AddMediaGallery } from "./Media";
import { OnChange } from "./OnChange";
import { PopupConditions } from "./PopupConditions";
import { Posts } from "./Posts";
import { Filters } from "./Filters";
import { Data } from "./Publish";
import { SavedBlocks, SavedLayouts, SavedPopups } from "./SavedBlocks";
import { Screenshots } from "./Screenshots";
Expand Down Expand Up @@ -147,6 +148,7 @@ export interface VISUAL_CONFIG {

elements?: {
posts: Posts;
filters: Filters;
};

//#endregion
Expand Down
3 changes: 3 additions & 0 deletions public/editor-client/src/utils/reader/array.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isT } from "fp-utilities";
import { Reader } from "./types";

export const read: Reader<Array<unknown>> = (v) => {
Expand All @@ -7,3 +8,5 @@ export const read: Reader<Array<unknown>> = (v) => {

return undefined;
};

export const isAllValuesValid = (arr: Array<unknown>) => arr.every(isT);

0 comments on commit d07a0f8

Please sign in to comment.