From 55e53582aa6f1465c1f45f92c0680deedb59b20c Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 23 Apr 2021 17:48:31 -0400 Subject: [PATCH] Adding listing_type to search. #143 (#264) * Adding listing_type to search. #143 * Adding async community searching. Fixes #262 * Some search additions. - Adding an async community picker. - Adding community_id to search page. * Adding creator search. * Accidentally removed line. --- package.json | 2 +- src/shared/components/communities.tsx | 2 +- src/shared/components/create-post.tsx | 40 +++- src/shared/components/main.tsx | 7 +- src/shared/components/navbar.tsx | 2 +- src/shared/components/person.tsx | 5 +- src/shared/components/post-form.tsx | 52 ++--- src/shared/components/post.tsx | 2 + src/shared/components/search.tsx | 305 +++++++++++++++++++++++++- src/shared/components/site-form.tsx | 8 +- src/shared/routes.ts | 2 +- src/shared/utils.ts | 90 ++++++++ yarn.lock | 8 +- 13 files changed, 461 insertions(+), 64 deletions(-) diff --git a/package.json b/package.json index b9377cf..1685494 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "eslint-plugin-prettier": "^3.3.1", "husky": "^6.0.0", "iso-639-1": "^2.1.9", - "lemmy-js-client": "0.11.0-rc.6", + "lemmy-js-client": "0.11.0-rc.9", "lint-staged": "^10.5.4", "mini-css-extract-plugin": "^1.4.1", "node-fetch": "^2.6.1", diff --git a/src/shared/components/communities.tsx b/src/shared/components/communities.tsx index ad12cca..efb92f9 100644 --- a/src/shared/components/communities.tsx +++ b/src/shared/components/communities.tsx @@ -273,7 +273,7 @@ export class Communities extends Component { handleSearchSubmit(i: Communities) { const searchParamEncoded = encodeURIComponent(i.state.searchText); i.context.router.history.push( - `/search/q/${searchParamEncoded}/type/Communities/sort/TopAll/page/1` + `/search/q/${searchParamEncoded}/type/Communities/sort/TopAll/listing_type/All/community_id/0/creator_id/0/page/1` ); } diff --git a/src/shared/components/create-post.tsx b/src/shared/components/create-post.tsx index f3d453b..72d8170 100644 --- a/src/shared/components/create-post.tsx +++ b/src/shared/components/create-post.tsx @@ -5,6 +5,7 @@ import { HtmlTags } from "./html-tags"; import { Spinner } from "./icon"; import { authField, + fetchLimit, isBrowser, setIsoData, setOptionalAuth, @@ -24,6 +25,8 @@ import { SortType, ListingType, PostView, + GetCommunity, + GetCommunityResponse, } from "lemmy-js-client"; import { i18n } from "../i18next"; import { InitialFetchRequest, PostFormParams } from "shared/interfaces"; @@ -66,15 +69,27 @@ export class CreatePost extends Component { } refetch() { - let listCommunitiesForm: ListCommunities = { - type_: ListingType.All, - sort: SortType.TopAll, - limit: 9999, - auth: authField(false), - }; - WebSocketService.Instance.send( - wsClient.listCommunities(listCommunitiesForm) - ); + if (this.params.community_id) { + let form: GetCommunity = { + id: this.params.community_id, + }; + WebSocketService.Instance.send(wsClient.getCommunity(form)); + } else if (this.params.community_name) { + let form: GetCommunity = { + name: this.params.community_name, + }; + WebSocketService.Instance.send(wsClient.getCommunity(form)); + } else { + let listCommunitiesForm: ListCommunities = { + type_: ListingType.All, + sort: SortType.TopAll, + limit: fetchLimit, + auth: authField(false), + }; + WebSocketService.Instance.send( + wsClient.listCommunities(listCommunitiesForm) + ); + } } componentWillUnmount() { @@ -163,7 +178,7 @@ export class CreatePost extends Component { let listCommunitiesForm: ListCommunities = { type_: ListingType.All, sort: SortType.TopAll, - limit: 9999, + limit: fetchLimit, }; setOptionalAuth(listCommunitiesForm, req.auth); return [req.client.listCommunities(listCommunitiesForm)]; @@ -180,6 +195,11 @@ export class CreatePost extends Component { this.state.communities = data.communities; this.state.loading = false; this.setState(this.state); + } else if (op == UserOperation.GetCommunity) { + let data = wsJsonToRes(msg).data; + this.state.communities = [data.community_view]; + this.state.loading = false; + this.setState(this.state); } } } diff --git a/src/shared/components/main.tsx b/src/shared/components/main.tsx index 05624d3..5374be5 100644 --- a/src/shared/components/main.tsx +++ b/src/shared/components/main.tsx @@ -60,6 +60,7 @@ import { authField, saveScrollPosition, restoreScrollPosition, + showLocal, } from "../utils"; import { i18n } from "../i18next"; import { T } from "inferno-i18next"; @@ -588,7 +589,7 @@ export class Main extends Component { @@ -650,10 +651,6 @@ export class Main extends Component { ); } - get showLocal(): boolean { - return this.isoData.site_res.federated_instances?.linked.length > 0; - } - get canAdmin(): boolean { return ( UserService.Instance.localUserView && diff --git a/src/shared/components/navbar.tsx b/src/shared/components/navbar.tsx index 35ed041..ff0f0ba 100644 --- a/src/shared/components/navbar.tsx +++ b/src/shared/components/navbar.tsx @@ -134,7 +134,7 @@ export class Navbar extends Component { } else { const searchParamEncoded = encodeURIComponent(searchParam); this.context.router.history.push( - `/search/q/${searchParamEncoded}/type/All/sort/TopAll/page/1` + `/search/q/${searchParamEncoded}/type/All/sort/TopAll/listing_type/All/community_id/0/creator_id/0/page/1` ); } } diff --git a/src/shared/components/person.tsx b/src/shared/components/person.tsx index 0870265..a38a36e 100644 --- a/src/shared/components/person.tsx +++ b/src/shared/components/person.tsx @@ -49,6 +49,7 @@ import { setOptionalAuth, saveScrollPosition, restoreScrollPosition, + showLocal, } from "../utils"; import { PersonListing } from "./person-listing"; import { HtmlTags } from "./html-tags"; @@ -655,9 +656,7 @@ export class Person extends Component { this.state.saveUserSettingsForm.default_listing_type ] } - showLocal={ - this.state.siteRes.federated_instances?.linked.length > 0 - } + showLocal={showLocal(this.isoData)} onChange={this.handleUserSettingsListingTypeChange} /> diff --git a/src/shared/components/post-form.tsx b/src/shared/components/post-form.tsx index e8a614f..81e8f46 100644 --- a/src/shared/components/post-form.tsx +++ b/src/shared/components/post-form.tsx @@ -15,6 +15,7 @@ import { Search, SearchType, SearchResponse, + ListingType, } from "lemmy-js-client"; import { WebSocketService, UserService } from "../services"; import { PostFormParams } from "../interfaces"; @@ -36,6 +37,9 @@ import { wsUserOp, wsClient, authField, + communityToChoice, + fetchCommunities, + choicesConfig, } from "../utils"; import autosize from "autosize"; @@ -406,6 +410,7 @@ export class PostForm extends Component { q: this.state.postForm.url, type_: SearchType.Url, sort: SortType.TopAll, + listing_type: ListingType.All, page: 1, limit: 6, auth: authField(false), @@ -435,6 +440,7 @@ export class PostForm extends Component { q: this.state.postForm.name, type_: SearchType.Posts, sort: SortType.TopAll, + listing_type: ListingType.All, community_id: this.state.postForm.community_id, page: 1, limit: 6, @@ -536,37 +542,7 @@ export class PostForm extends Component { if (isBrowser()) { let selectId: any = document.getElementById("post-community"); if (selectId) { - this.choices = new Choices(selectId, { - shouldSort: false, - classNames: { - containerOuter: "choices", - containerInner: "choices__inner bg-light border-0", - input: "form-control", - inputCloned: "choices__input--cloned", - list: "choices__list", - listItems: "choices__list--multiple", - listSingle: "choices__list--single", - listDropdown: "choices__list--dropdown", - item: "choices__item bg-light", - itemSelectable: "choices__item--selectable", - itemDisabled: "choices__item--disabled", - itemChoice: "choices__item--choice", - placeholder: "choices__placeholder", - group: "choices__group", - groupHeading: "choices__heading", - button: "choices__button", - activeState: "is-active", - focusState: "is-focused", - openState: "is-open", - disabledState: "is-disabled", - highlightedState: "text-info", - selectedState: "text-info", - flippedState: "is-flipped", - loadingState: "is-loading", - noResults: "has-no-results", - noChoices: "has-no-choices", - }, - }); + this.choices = new Choices(selectId, choicesConfig); this.choices.passedElement.element.addEventListener( "choice", (e: any) => { @@ -575,6 +551,20 @@ export class PostForm extends Component { }, false ); + this.choices.passedElement.element.addEventListener( + "search", + debounce(async (e: any) => { + let communities = (await fetchCommunities(e.detail.value)) + .communities; + this.choices.setChoices( + communities.map(cv => communityToChoice(cv)), + "value", + "label", + true + ); + }, 400), + false + ); } } diff --git a/src/shared/components/post.tsx b/src/shared/components/post.tsx index e27a73d..f66b94e 100644 --- a/src/shared/components/post.tsx +++ b/src/shared/components/post.tsx @@ -21,6 +21,7 @@ import { SearchResponse, GetSiteResponse, GetCommunityResponse, + ListingType, } from "lemmy-js-client"; import { CommentSortType, @@ -132,6 +133,7 @@ export class Post extends Component { q: this.state.postRes.post_view.post.url, type_: SearchType.Url, sort: SortType.TopAll, + listing_type: ListingType.All, page: 1, limit: 6, auth: authField(false), diff --git a/src/shared/components/search.tsx b/src/shared/components/search.tsx index e06829b..9f0c04e 100644 --- a/src/shared/components/search.tsx +++ b/src/shared/components/search.tsx @@ -13,6 +13,11 @@ import { PostResponse, CommentResponse, Site, + ListingType, + ListCommunities, + ListCommunitiesResponse, + GetCommunity, + GetPersonDetails, } from "lemmy-js-client"; import { WebSocketService } from "../services"; import { @@ -32,6 +37,17 @@ import { setOptionalAuth, saveScrollPosition, restoreScrollPosition, + routeListingTypeToEnum, + showLocal, + isBrowser, + choicesConfig, + debounce, + fetchCommunities, + communityToChoice, + hostname, + fetchUsers, + personToChoice, + capitalizeFirstLetter, } from "../utils"; import { PostListing } from "./post-listing"; import { HtmlTags } from "./html-tags"; @@ -39,14 +55,23 @@ import { Spinner } from "./icon"; import { PersonListing } from "./person-listing"; import { CommunityLink } from "./community-link"; import { SortSelect } from "./sort-select"; +import { ListingTypeSelect } from "./listing-type-select"; import { CommentNodes } from "./comment-nodes"; import { i18n } from "../i18next"; import { InitialFetchRequest } from "shared/interfaces"; +var Choices; +if (isBrowser()) { + Choices = require("choices.js"); +} + interface SearchProps { q: string; type_: SearchType; sort: SortType; + listingType: ListingType; + communityId: number; + creatorId: number; page: number; } @@ -54,8 +79,13 @@ interface SearchState { q: string; type_: SearchType; sort: SortType; + listingType: ListingType; + communityId: number; + creatorId: number; page: number; searchResponse: SearchResponse; + communities: CommunityView[]; + creator?: PersonViewSafe; loading: boolean; site: Site; searchText: string; @@ -65,18 +95,30 @@ interface UrlParams { q?: string; type_?: SearchType; sort?: SortType; + listingType?: ListingType; + communityId?: number; + creatorId?: number; page?: number; } export class Search extends Component { private isoData = setIsoData(this.context); + private communityChoices: any; + private creatorChoices: any; private subscription: Subscription; private emptyState: SearchState = { q: Search.getSearchQueryFromProps(this.props.match.params.q), type_: Search.getSearchTypeFromProps(this.props.match.params.type), sort: Search.getSortTypeFromProps(this.props.match.params.sort), + listingType: Search.getListingTypeFromProps( + this.props.match.params.listing_type + ), page: Search.getPageFromProps(this.props.match.params.page), searchText: Search.getSearchQueryFromProps(this.props.match.params.q), + communityId: Search.getCommunityIdFromProps( + this.props.match.params.community_id + ), + creatorId: Search.getCreatorIdFromProps(this.props.match.params.creator_id), searchResponse: { type_: null, posts: [], @@ -86,6 +128,7 @@ export class Search extends Component { }, loading: true, site: this.isoData.site_res.site_view.site, + communities: [], }; static getSearchQueryFromProps(q: string): string { @@ -100,6 +143,18 @@ export class Search extends Component { return sort ? routeSortTypeToEnum(sort) : SortType.TopAll; } + static getListingTypeFromProps(listingType: string): ListingType { + return listingType ? routeListingTypeToEnum(listingType) : ListingType.All; + } + + static getCommunityIdFromProps(id: string): number { + return id ? Number(id) : 0; + } + + static getCreatorIdFromProps(id: string): number { + return id ? Number(id) : 0; + } + static getPageFromProps(page: string): number { return page ? Number(page) : 1; } @@ -109,18 +164,33 @@ export class Search extends Component { this.state = this.emptyState; this.handleSortChange = this.handleSortChange.bind(this); + this.handleListingTypeChange = this.handleListingTypeChange.bind(this); this.parseMessage = this.parseMessage.bind(this); this.subscription = wsSubscribe(this.parseMessage); // Only fetch the data if coming from another route - if (this.state.q != "") { - if (this.isoData.path == this.context.router.route.match.url) { - this.state.searchResponse = this.isoData.routeData[0]; + if (this.isoData.path == this.context.router.route.match.url) { + let singleOrMultipleCommunities = this.isoData.routeData[0]; + if (singleOrMultipleCommunities.communities) { + this.state.communities = this.isoData.routeData[0].communities; + } else { + this.state.communities = [this.isoData.routeData[0].community_view]; + } + + let creator = this.isoData.routeData[1]; + if (creator?.person_view) { + this.state.creator = this.isoData.routeData[1].person_view; + } + if (this.state.q != "") { + this.state.searchResponse = this.isoData.routeData[2]; this.state.loading = false; } else { this.search(); } + } else { + this.fetchCommunities(); + this.search(); } } @@ -129,26 +199,85 @@ export class Search extends Component { saveScrollPosition(this.context); } + componentDidMount() { + this.setupCommunityFilter(); + this.setupCreatorFilter(); + } + static getDerivedStateFromProps(props: any): SearchProps { return { q: Search.getSearchQueryFromProps(props.match.params.q), type_: Search.getSearchTypeFromProps(props.match.params.type), sort: Search.getSortTypeFromProps(props.match.params.sort), + listingType: Search.getListingTypeFromProps( + props.match.params.listing_type + ), + communityId: Search.getCommunityIdFromProps( + props.match.params.community_id + ), + creatorId: Search.getCreatorIdFromProps(props.match.params.creator_id), page: Search.getPageFromProps(props.match.params.page), }; } + fetchCommunities() { + let listCommunitiesForm: ListCommunities = { + type_: ListingType.All, + sort: SortType.TopAll, + limit: fetchLimit, + auth: authField(false), + }; + WebSocketService.Instance.send( + wsClient.listCommunities(listCommunitiesForm) + ); + } + static fetchInitialData(req: InitialFetchRequest): Promise[] { let pathSplit = req.path.split("/"); let promises: Promise[] = []; + let communityId = this.getCommunityIdFromProps(pathSplit[11]); + if (communityId !== 0) { + let getCommunityForm: GetCommunity = { + id: communityId, + }; + setOptionalAuth(getCommunityForm, req.auth); + promises.push(req.client.getCommunity(getCommunityForm)); + } else { + let listCommunitiesForm: ListCommunities = { + type_: ListingType.All, + sort: SortType.TopAll, + limit: fetchLimit, + }; + setOptionalAuth(listCommunitiesForm, req.auth); + promises.push(req.client.listCommunities(listCommunitiesForm)); + } + + let creatorId = this.getCreatorIdFromProps(pathSplit[13]); + if (creatorId !== 0) { + let getCreatorForm: GetPersonDetails = { + person_id: creatorId, + }; + setOptionalAuth(getCreatorForm, req.auth); + promises.push(req.client.getPersonDetails(getCreatorForm)); + } else { + promises.push(Promise.resolve()); + } + let form: SearchForm = { q: this.getSearchQueryFromProps(pathSplit[3]), type_: this.getSearchTypeFromProps(pathSplit[5]), sort: this.getSortTypeFromProps(pathSplit[7]), - page: this.getPageFromProps(pathSplit[9]), + listing_type: this.getListingTypeFromProps(pathSplit[9]), + page: this.getPageFromProps(pathSplit[15]), limit: fetchLimit, }; + if (communityId !== 0) { + form.community_id = communityId; + } + if (creatorId !== 0) { + form.creator_id = creatorId; + } setOptionalAuth(form, req.auth); if (form.q != "") { @@ -163,6 +292,9 @@ export class Search extends Component { lastState.q !== this.state.q || lastState.type_ !== this.state.type_ || lastState.sort !== this.state.sort || + lastState.listingType !== this.state.listingType || + lastState.communityId !== this.state.communityId || + lastState.creatorId !== this.state.creatorId || lastState.page !== this.state.page ) { this.setState({ loading: true, searchText: this.state.q }); @@ -242,6 +374,13 @@ export class Search extends Component { + + + { hideMostComments /> +
+ {this.state.communities.length > 0 && this.communityFilter()} + {this.creatorFilter()} +
); } @@ -413,6 +556,60 @@ export class Search extends Component { ); } + communityFilter() { + return ( +
+ +
+ +
+
+ ); + } + + creatorFilter() { + return ( +
+ +
+ +
+
+ ); + } + paginator() { return (
@@ -460,16 +657,76 @@ export class Search extends Component { q: this.state.q, type_: this.state.type_, sort: this.state.sort, + listing_type: this.state.listingType, page: this.state.page, limit: fetchLimit, auth: authField(false), }; + if (this.state.communityId !== 0) { + form.community_id = this.state.communityId; + } + if (this.state.creatorId !== 0) { + form.creator_id = this.state.creatorId; + } if (this.state.q != "") { WebSocketService.Instance.send(wsClient.search(form)); } } + setupCommunityFilter() { + if (isBrowser()) { + let selectId: any = document.getElementById("community-filter"); + if (selectId) { + this.communityChoices = new Choices(selectId, choicesConfig); + this.communityChoices.passedElement.element.addEventListener( + "choice", + (e: any) => { + this.handleCommunityFilterChange(Number(e.detail.choice.value)); + }, + false + ); + this.communityChoices.passedElement.element.addEventListener( + "search", + debounce(async (e: any) => { + let communities = (await fetchCommunities(e.detail.value)) + .communities; + let choices = communities.map(cv => communityToChoice(cv)); + choices.unshift({ value: "0", label: i18n.t("all") }); + this.communityChoices.setChoices(choices, "value", "label", true); + }, 400), + false + ); + } + } + } + + setupCreatorFilter() { + if (isBrowser()) { + let selectId: any = document.getElementById("creator-filter"); + if (selectId) { + this.creatorChoices = new Choices(selectId, choicesConfig); + this.creatorChoices.passedElement.element.addEventListener( + "choice", + (e: any) => { + this.handleCreatorFilterChange(Number(e.detail.choice.value)); + }, + false + ); + this.creatorChoices.passedElement.element.addEventListener( + "search", + debounce(async (e: any) => { + let creators = (await fetchUsers(e.detail.value)).users; + let choices = creators.map(pvs => personToChoice(pvs)); + choices.unshift({ value: "0", label: i18n.t("all") }); + this.creatorChoices.setChoices(choices, "value", "label", true); + }, 400), + false + ); + } + } + } + handleSortChange(val: SortType) { this.updateUrl({ sort: val, page: 1 }); } @@ -481,11 +738,35 @@ export class Search extends Component { }); } + handleListingTypeChange(val: ListingType) { + this.updateUrl({ + listingType: val, + page: 1, + }); + } + + handleCommunityFilterChange(communityId: number) { + this.updateUrl({ + communityId, + page: 1, + }); + } + + handleCreatorFilterChange(creatorId: number) { + this.updateUrl({ + creatorId, + page: 1, + }); + } + handleSearchSubmit(i: Search, event: any) { event.preventDefault(); i.updateUrl({ q: i.state.searchText, type_: i.state.type_, + listingType: i.state.listingType, + communityId: i.state.communityId, + creatorId: i.state.creatorId, sort: i.state.sort, page: i.state.page, }); @@ -499,10 +780,19 @@ export class Search extends Component { const qStr = paramUpdates.q || this.state.q; const qStrEncoded = encodeURIComponent(qStr); const typeStr = paramUpdates.type_ || this.state.type_; + const listingTypeStr = paramUpdates.listingType || this.state.listingType; const sortStr = paramUpdates.sort || this.state.sort; + const communityId = + paramUpdates.communityId == 0 + ? 0 + : paramUpdates.communityId || this.state.communityId; + const creatorId = + paramUpdates.creatorId == 0 + ? 0 + : paramUpdates.creatorId || this.state.creatorId; const page = paramUpdates.page || this.state.page; this.props.history.push( - `/search/q/${qStrEncoded}/type/${typeStr}/sort/${sortStr}/page/${page}` + `/search/q/${qStrEncoded}/type/${typeStr}/sort/${sortStr}/listing_type/${listingTypeStr}/community_id/${communityId}/creator_id/${creatorId}/page/${page}` ); } @@ -530,6 +820,11 @@ export class Search extends Component { let data = wsJsonToRes(msg).data; createPostLikeFindRes(data.post_view, this.state.searchResponse.posts); this.setState(this.state); + } else if (op == UserOperation.ListCommunities) { + let data = wsJsonToRes(msg).data; + this.state.communities = data.communities; + this.setState(this.state); + this.setupCommunityFilter(); } } } diff --git a/src/shared/components/site-form.tsx b/src/shared/components/site-form.tsx index 25fc1bc..1e7f0cd 100644 --- a/src/shared/components/site-form.tsx +++ b/src/shared/components/site-form.tsx @@ -3,7 +3,7 @@ import { Prompt } from "inferno-router"; import { MarkdownTextArea } from "./markdown-textarea"; import { Spinner } from "./icon"; import { ImageUploadForm } from "./image-upload-form"; -import { Site, EditSite } from "lemmy-js-client"; +import { Site, EditSite, CreateSite } from "lemmy-js-client"; import { WebSocketService } from "../services"; import { authField, @@ -250,7 +250,11 @@ export class SiteForm extends Component { if (i.props.site) { WebSocketService.Instance.send(wsClient.editSite(i.state.siteForm)); } else { - WebSocketService.Instance.send(wsClient.createSite(i.state.siteForm)); + let form: CreateSite = { + name: i.state.siteForm.name || "My site", + ...i.state.siteForm, + }; + WebSocketService.Instance.send(wsClient.createSite(form)); } i.setState(i.state); } diff --git a/src/shared/routes.ts b/src/shared/routes.ts index b33057d..cae8c50 100644 --- a/src/shared/routes.ts +++ b/src/shared/routes.ts @@ -133,7 +133,7 @@ export const routes: IRoutePropsWithFetch[] = [ fetchInitialData: req => AdminSettings.fetchInitialData(req), }, { - path: `/search/q/:q/type/:type/sort/:sort/page/:page`, + path: `/search/q/:q/type/:type/sort/:sort/listing_type/:listing_type/community_id/:community_id/creator_id/:creator_id/page/:page`, component: Search, fetchInitialData: req => Search.fetchInitialData(req), }, diff --git a/src/shared/utils.ts b/src/shared/utils.ts index b0ab2c8..4901c96 100644 --- a/src/shared/utils.ts +++ b/src/shared/utils.ts @@ -46,6 +46,7 @@ import { LemmyWebsocket, PersonViewSafe, CommunityView, + LemmyHttp, } from "lemmy-js-client"; import { @@ -70,6 +71,7 @@ import moment from "moment"; import { Subscription } from "rxjs"; import { retryWhen, delay, take } from "rxjs/operators"; import { i18n } from "./i18next"; +import { httpBase } from "./env"; export const wsClient = new LemmyWebsocket(); @@ -747,6 +749,7 @@ function personSearch(text: string, cb: (persons: PersonTribute[]) => any) { q: text, type_: SearchType.Users, sort: SortType.TopAll, + listing_type: ListingType.All, page: 1, limit: mentionDropdownFetchLimit, auth: authField(false), @@ -792,6 +795,7 @@ function communitySearch( q: text, type_: SearchType.Communities, sort: SortType.TopAll, + listing_type: ListingType.All, page: 1, limit: mentionDropdownFetchLimit, auth: authField(false), @@ -1226,3 +1230,89 @@ export function restoreScrollPosition(context: any) { let y = Number(sessionStorage.getItem(`scrollPosition_${path}`)); window.scrollTo(0, y); } + +export function showLocal(isoData: IsoData): boolean { + return isoData.site_res.federated_instances?.linked.length > 0; +} + +interface ChoicesValue { + value: string; + label: string; +} + +export function communityToChoice(cv: CommunityView): ChoicesValue { + let choice: ChoicesValue = { + value: cv.community.id.toString(), + label: cv.community.name, + }; + return choice; +} + +export function personToChoice(pvs: PersonViewSafe): ChoicesValue { + let choice: ChoicesValue = { + value: pvs.person.id.toString(), + label: pvs.person.name, + }; + return choice; +} + +export async function fetchCommunities(q: string) { + let form: Search = { + q, + type_: SearchType.Communities, + sort: SortType.TopAll, + listing_type: ListingType.All, + page: 1, + limit: fetchLimit, + auth: authField(false), + }; + let client = new LemmyHttp(httpBase); + return client.search(form); +} + +export async function fetchUsers(q: string) { + let form: Search = { + q, + type_: SearchType.Users, + sort: SortType.TopAll, + listing_type: ListingType.All, + page: 1, + limit: fetchLimit, + auth: authField(false), + }; + let client = new LemmyHttp(httpBase); + return client.search(form); +} + +export const choicesConfig = { + shouldSort: false, + searchResultLimit: fetchLimit, + classNames: { + containerOuter: "choices", + containerInner: "choices__inner bg-light border-0", + input: "form-control", + inputCloned: "choices__input--cloned", + list: "choices__list", + listItems: "choices__list--multiple", + listSingle: "choices__list--single", + listDropdown: "choices__list--dropdown", + item: "choices__item bg-light", + itemSelectable: "choices__item--selectable", + itemDisabled: "choices__item--disabled", + itemChoice: "choices__item--choice", + placeholder: "choices__placeholder", + group: "choices__group", + groupHeading: "choices__heading", + button: "choices__button", + activeState: "is-active", + focusState: "is-focused", + openState: "is-open", + disabledState: "is-disabled", + highlightedState: "text-info", + selectedState: "text-info", + flippedState: "is-flipped", + loadingState: "is-loading", + noResults: "has-no-results", + noChoices: "has-no-choices", + }, +}; diff --git a/yarn.lock b/yarn.lock index cf01f3f..35d861a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5125,10 +5125,10 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -lemmy-js-client@0.11.0-rc.6: - version "0.11.0-rc.6" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.11.0-rc.6.tgz#897671c8e24be8ba2a6074efc63264c421969380" - integrity sha512-/AIws5bidcNIi8wSzJx7mwo5Ip2u78s4/bMdEyfEqWKWqdNwEKV/6eYnyThA3j9gYXjd8ty731s0l0kSs/vmhA== +lemmy-js-client@0.11.0-rc.9: + version "0.11.0-rc.9" + resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.11.0-rc.9.tgz#f8b1e3924388c6e7f719f052ba1568f4d210cabc" + integrity sha512-697hLvHPr5+ZkJkFTaXl3y7Dt1va2Dghx9uvu/kZyZQZGVk2lL10R50SDaWsThyQKFBT4kiS1JZI+R3szzZEZQ== levn@^0.4.1: version "0.4.1" -- 2.44.1