Create community, Create post, and instances pages done.

This commit is contained in:
Dessalines 2020-09-07 17:24:48 -05:00
parent cde3c266f2
commit a5aeba3ad0
9 changed files with 308 additions and 324 deletions

View file

@ -52,13 +52,16 @@ export class Communities extends Component<any, CommunitiesState> {
constructor(props: any, context: any) {
super(props, context);
this.state = this.emptyState;
this.parseMessage = this.parseMessage.bind(this);
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
// Only fetch the data if coming from another route
if (this.isoData.path == this.context.router.route.match.url) {
this.state.communities = this.isoData.routeData[0].communities;
this.state.communities.sort(
(a, b) => b.number_of_subscribers - a.number_of_subscribers
);
this.state.loading = false;
} else {
this.refetch();

View file

@ -6,7 +6,6 @@ import {
CommunityForm as CommunityFormI,
UserOperation,
Category,
ListCategoriesResponse,
CommunityResponse,
WebSocketJsonResponse,
Community,
@ -20,6 +19,7 @@ import { ImageUploadForm } from './image-upload-form';
interface CommunityFormProps {
community?: Community; // If a community is given, that means this is an edit
categories: Category[];
onCancel?(): any;
onCreate?(community: Community): any;
onEdit?(community: Community): any;
@ -28,7 +28,6 @@ interface CommunityFormProps {
interface CommunityFormState {
communityForm: CommunityFormI;
categories: Category[];
loading: boolean;
}
@ -43,12 +42,11 @@ export class CommunityForm extends Component<
communityForm: {
name: null,
title: null,
category_id: null,
category_id: this.props.categories[0].id,
nsfw: false,
icon: null,
banner: null,
},
categories: [],
loading: false,
};
@ -88,8 +86,6 @@ export class CommunityForm extends Component<
err => console.error(err),
() => console.log('complete')
);
WebSocketService.Instance.listCategories();
}
componentDidUpdate() {
@ -218,7 +214,7 @@ export class CommunityForm extends Component<
value={this.state.communityForm.category_id}
onInput={linkEvent(this, this.handleCommunityCategoryChange)}
>
{this.state.categories.map(category => (
{this.props.categories.map(category => (
<option value={category.id}>{category.name}</option>
))}
</select>
@ -344,13 +340,6 @@ export class CommunityForm extends Component<
this.state.loading = false;
this.setState(this.state);
return;
} else if (res.op == UserOperation.ListCategories) {
let data = res.data as ListCategoriesResponse;
this.state.categories = data.categories;
if (!this.props.community) {
this.state.communityForm.category_id = data.categories[0].id;
}
this.setState(this.state);
} else if (res.op == UserOperation.CreateCommunity) {
let data = res.data as CommunityResponse;
this.state.loading = false;

View file

@ -1,87 +1,95 @@
import { Component } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import { CommunityForm } from './community-form';
import {
Community,
UserOperation,
WebSocketJsonResponse,
GetSiteResponse,
Site,
ListCategoriesResponse,
Category,
} from 'lemmy-js-client';
import { toast, wsJsonToRes } from '../utils';
import {
setIsoData,
toast,
wsJsonToRes,
wsSubscribe,
isBrowser,
lemmyHttp,
} from '../utils';
import { WebSocketService, UserService } from '../services';
import { i18n } from '../i18next';
interface CreateCommunityState {
site: Site;
categories: Category[];
loading: boolean;
}
export class CreateCommunity extends Component<any, CreateCommunityState> {
private isoData = setIsoData(this.context);
private subscription: Subscription;
private emptyState: CreateCommunityState = {
site: {
id: undefined,
name: undefined,
creator_id: undefined,
published: undefined,
creator_name: undefined,
number_of_users: undefined,
number_of_posts: undefined,
number_of_comments: undefined,
number_of_communities: undefined,
enable_downvotes: undefined,
open_registration: undefined,
enable_nsfw: undefined,
},
site: this.isoData.site.site,
categories: [],
loading: true,
};
constructor(props: any, context: any) {
super(props, context);
this.handleCommunityCreate = this.handleCommunityCreate.bind(this);
this.state = this.emptyState;
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
// TODO not sure if this works
if (!UserService.Instance.user) {
toast(i18n.t('not_logged_in'), 'danger');
this.context.router.history.push(`/login`);
}
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
);
WebSocketService.Instance.getSite();
// Only fetch the data if coming from another route
if (this.isoData.path == this.context.router.route.match.url) {
this.state.categories = this.isoData.routeData[0].categories;
this.state.loading = false;
} else {
WebSocketService.Instance.listCategories();
}
}
componentWillUnmount() {
if (isBrowser()) {
this.subscription.unsubscribe();
}
}
get documentTitle(): string {
if (this.state.site.name) {
return `${i18n.t('create_community')} - ${this.state.site.name}`;
} else {
return 'Lemmy';
}
}
render() {
return (
<div class="container">
<Helmet title={this.documentTitle} />
{this.state.loading ? (
<h5>
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
</h5>
) : (
<div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5>{i18n.t('create_community')}</h5>
<CommunityForm
categories={this.state.categories}
onCreate={this.handleCommunityCreate}
enableNsfw={this.state.site.enable_nsfw}
/>
</div>
</div>
)}
</div>
);
}
@ -90,15 +98,20 @@ export class CreateCommunity extends Component<any, CreateCommunityState> {
this.props.history.push(`/c/${community.name}`);
}
static fetchInitialData(_auth: string, _path: string): Promise<any>[] {
return [lemmyHttp.listCategories()];
}
parseMessage(msg: WebSocketJsonResponse) {
console.log(msg);
let res = wsJsonToRes(msg);
if (msg.error) {
// Toast errors are already handled by community-form
return;
} else if (res.op == UserOperation.GetSite) {
let data = res.data as GetSiteResponse;
this.state.site = data.site;
} else if (res.op == UserOperation.ListCategories) {
let data = res.data as ListCategoriesResponse;
this.state.categories = data.categories;
this.state.loading = false;
this.setState(this.state);
}
}

View file

@ -1,40 +1,41 @@
import { Component } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import { PostForm } from './post-form';
import { toast, wsJsonToRes } from '../utils';
import { WebSocketService, UserService } from '../services';
import {
lemmyHttp,
setAuth,
setIsoData,
toast,
wsJsonToRes,
wsSubscribe,
} from '../utils';
import { UserService, WebSocketService } from '../services';
import {
UserOperation,
PostFormParams,
WebSocketJsonResponse,
GetSiteResponse,
ListCommunitiesResponse,
Community,
Site,
ListCommunitiesForm,
SortType,
} from 'lemmy-js-client';
import { i18n } from '../i18next';
interface CreatePostState {
site: Site;
communities: Community[];
loading: boolean;
}
export class CreatePost extends Component<any, CreatePostState> {
private isoData = setIsoData(this.context);
private subscription: Subscription;
private emptyState: CreatePostState = {
site: {
id: undefined,
name: undefined,
creator_id: undefined,
published: undefined,
creator_name: undefined,
number_of_users: undefined,
number_of_posts: undefined,
number_of_comments: undefined,
number_of_communities: undefined,
enable_downvotes: undefined,
open_registration: undefined,
enable_nsfw: undefined,
},
site: this.isoData.site.site,
communities: [],
loading: true,
};
constructor(props: any, context: any) {
@ -47,15 +48,24 @@ export class CreatePost extends Component<any, CreatePostState> {
this.context.router.history.push(`/login`);
}
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
);
this.parseMessage = this.parseMessage.bind(this);
this.subscription = wsSubscribe(this.parseMessage);
WebSocketService.Instance.getSite();
// Only fetch the data if coming from another route
if (this.isoData.path == this.context.router.route.match.url) {
this.state.communities = this.isoData.routeData[0].communities;
this.state.loading = false;
} else {
this.refetch();
}
}
refetch() {
let listCommunitiesForm: ListCommunitiesForm = {
sort: SortType.TopAll,
limit: 9999,
};
WebSocketService.Instance.listCommunities(listCommunitiesForm);
}
componentWillUnmount() {
@ -63,21 +73,25 @@ export class CreatePost extends Component<any, CreatePostState> {
}
get documentTitle(): string {
if (this.state.site.name) {
return `${i18n.t('create_post')} - ${this.state.site.name}`;
} else {
return 'Lemmy';
}
}
render() {
return (
<div class="container">
<Helmet title={this.documentTitle} />
{this.state.loading ? (
<h5>
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
</h5>
) : (
<div class="row">
<div class="col-12 col-lg-6 offset-lg-3 mb-4">
<h5>{i18n.t('create_post')}</h5>
<PostForm
communities={this.state.communities}
onCreate={this.handlePostCreate}
params={this.params}
enableDownvotes={this.state.site.enable_downvotes}
@ -85,6 +99,7 @@ export class CreatePost extends Component<any, CreatePostState> {
/>
</div>
</div>
)}
</div>
);
}
@ -110,22 +125,32 @@ export class CreatePost extends Component<any, CreatePostState> {
return lastLocation.split('/c/')[1];
}
}
return;
return null;
}
handlePostCreate(id: number) {
this.props.history.push(`/post/${id}`);
}
static fetchInitialData(auth: string, _path: string): Promise<any>[] {
let listCommunitiesForm: ListCommunitiesForm = {
sort: SortType.TopAll,
limit: 9999,
};
setAuth(listCommunitiesForm, auth);
return [lemmyHttp.listCommunities(listCommunitiesForm)];
}
parseMessage(msg: WebSocketJsonResponse) {
console.log(msg);
let res = wsJsonToRes(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
return;
} else if (res.op == UserOperation.GetSite) {
let data = res.data as GetSiteResponse;
this.state.site = data.site;
} else if (res.op == UserOperation.ListCommunities) {
let data = res.data as ListCommunitiesResponse;
this.state.communities = data.communities;
this.state.loading = false;
this.setState(this.state);
}
}

View file

@ -1,68 +1,32 @@
import { Component } from 'inferno';
import { Helmet } from 'inferno-helmet';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
UserOperation,
WebSocketJsonResponse,
GetSiteResponse,
} from 'lemmy-js-client';
import { WebSocketService } from '../services';
import { wsJsonToRes, toast, isBrowser } from '../utils';
import { GetSiteResponse } from 'lemmy-js-client';
import { setIsoData } from '../utils';
import { i18n } from '../i18next';
interface InstancesState {
loading: boolean;
siteRes: GetSiteResponse;
}
export class Instances extends Component<any, InstancesState> {
private subscription: Subscription;
private isoData = setIsoData(this.context);
private emptyState: InstancesState = {
loading: true,
siteRes: undefined,
siteRes: this.isoData.site,
};
constructor(props: any, context: any) {
super(props, context);
this.state = this.emptyState;
if (isBrowser()) {
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
);
WebSocketService.Instance.getSite();
}
}
componentWillUnmount() {
this.subscription.unsubscribe();
}
get documentTitle(): string {
if (this.state.siteRes) {
return `${i18n.t('instances')} - ${this.state.siteRes.site.name}`;
} else {
return 'Lemmy';
}
}
render() {
return (
<div class="container">
<Helmet title={this.documentTitle} />
{this.state.loading ? (
<h5 class="">
<svg class="icon icon-spinner spin">
<use xlinkHref="#icon-spinner"></use>
</svg>
</h5>
) : (
<div>
<h5>{i18n.t('linked_instances')}</h5>
{this.state.siteRes &&
@ -80,22 +44,7 @@ export class Instances extends Component<any, InstancesState> {
<div>{i18n.t('none_found')}</div>
)}
</div>
)}
</div>
);
}
parseMessage(msg: WebSocketJsonResponse) {
console.log(msg);
let res = wsJsonToRes(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
return;
} else if (res.op == UserOperation.GetSite) {
let data = res.data as GetSiteResponse;
this.state.siteRes = data;
this.state.loading = false;
this.setState(this.state);
}
}
}

View file

@ -8,10 +8,10 @@ import {
setupTribute,
pictrsDeleteToast,
setupTippy,
isBrowser,
} from '../utils';
import { UserService } from '../services';
import autosize from 'autosize';
import Tribute from 'tributejs/src/Tribute.js';
import { i18n } from '../i18next';
interface MarkdownTextAreaProps {
@ -41,7 +41,7 @@ export class MarkdownTextArea extends Component<
> {
private id = `comment-textarea-${randomStr()}`;
private formId = `comment-form-${randomStr()}`;
private tribute: Tribute;
private tribute: any;
private emptyState: MarkdownTextAreaState = {
content: this.props.initialContent,
previewMode: false,
@ -52,8 +52,9 @@ export class MarkdownTextArea extends Component<
constructor(props: any, context: any) {
super(props, context);
// TODO
/* this.tribute = setupTribute(); */
if (isBrowser()) {
this.tribute = setupTribute();
}
this.state = this.emptyState;
}

View file

@ -3,7 +3,6 @@ import { Prompt } from 'inferno-router';
import { PostListings } from './post-listings';
import { MarkdownTextArea } from './markdown-textarea';
import { Subscription } from 'rxjs';
import { retryWhen, delay, take } from 'rxjs/operators';
import {
PostForm as PostFormI,
PostFormParams,
@ -11,8 +10,6 @@ import {
PostResponse,
UserOperation,
Community,
ListCommunitiesResponse,
ListCommunitiesForm,
SortType,
SearchForm,
SearchType,
@ -34,14 +31,22 @@ import {
hostname,
pictrsDeleteToast,
validTitle,
wsSubscribe,
isBrowser,
} from '../utils';
import Choices from 'choices.js';
var Choices;
if (isBrowser()) {
Choices = require('choices.js');
}
import { i18n } from '../i18next';
const MAX_POST_TITLE_LENGTH = 200;
interface PostFormProps {
post?: Post; // If a post is given, that means this is an edit
communities: Community[];
params?: PostFormParams;
onCancel?(): any;
onCreate?(id: number): any;
@ -52,7 +57,6 @@ interface PostFormProps {
interface PostFormState {
postForm: PostFormI;
communities: Community[];
loading: boolean;
imageLoading: boolean;
previewMode: boolean;
@ -64,7 +68,7 @@ interface PostFormState {
export class PostForm extends Component<PostFormProps, PostFormState> {
private id = `post-form-${randomStr()}`;
private subscription: Subscription;
private choices: Choices;
private choices: any;
private emptyState: PostFormState = {
postForm: {
name: null,
@ -72,7 +76,6 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
auth: null,
community_id: null,
},
communities: [],
loading: false,
imageLoading: false,
previewMode: false,
@ -112,24 +115,12 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
}
}
this.subscription = WebSocketService.Instance.subject
.pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
.subscribe(
msg => this.parseMessage(msg),
err => console.error(err),
() => console.log('complete')
);
let listCommunitiesForm: ListCommunitiesForm = {
sort: SortType.TopAll,
limit: 9999,
};
WebSocketService.Instance.listCommunities(listCommunitiesForm);
this.subscription = wsSubscribe(this.parseMessage);
}
componentDidMount() {
setupTippy();
this.setupCommunities();
}
componentDidUpdate() {
@ -209,7 +200,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
onChange={linkEvent(this, this.handleImageUpload)}
/>
</form>
{validURL(this.state.postForm.url) && (
{this.state.postForm.url && validURL(this.state.postForm.url) && (
<a
href={`${archiveUrl}/?run=1&url=${encodeURIComponent(
this.state.postForm.url
@ -305,7 +296,7 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
onInput={linkEvent(this, this.handlePostCommunityChange)}
>
<option>{i18n.t('select_a_community')}</option>
{this.state.communities.map(community => (
{this.props.communities.map(community => (
<option value={community.id}>
{community.local
? community.name
@ -531,63 +522,53 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
});
}
parseMessage(msg: WebSocketJsonResponse) {
let res = wsJsonToRes(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
this.state.loading = false;
this.setState(this.state);
return;
} else if (res.op == UserOperation.ListCommunities) {
let data = res.data as ListCommunitiesResponse;
this.state.communities = data.communities;
setupCommunities() {
if (this.props.post) {
this.state.postForm.community_id = this.props.post.community_id;
} else if (this.props.params && this.props.params.community) {
let foundCommunityId = data.communities.find(
let foundCommunityId = this.props.communities.find(
r => r.name == this.props.params.community
).id;
this.state.postForm.community_id = foundCommunityId;
} else {
// By default, the null valued 'Select a Community'
}
this.setState(this.state);
// Set up select searching
if (isBrowser()) {
let selectId: any = document.getElementById('post-community');
if (selectId) {
// TODO
/* this.choices = new Choices(selectId, { */
/* shouldSort: false, */
/* classNames: { */
/* containerOuter: 'choices', */
/* containerInner: 'choices__inner bg-secondary 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-secondary', */
/* 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, {
shouldSort: false,
classNames: {
containerOuter: 'choices',
containerInner: 'choices__inner bg-secondary 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-secondary',
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.passedElement.element.addEventListener(
'choice',
(e: any) => {
@ -597,6 +578,16 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
false
);
}
}
}
parseMessage(msg: WebSocketJsonResponse) {
let res = wsJsonToRes(msg);
if (msg.error) {
toast(i18n.t(msg.error), 'danger');
this.state.loading = false;
this.setState(this.state);
return;
} else if (res.op == UserOperation.CreatePost) {
let data = res.data as PostResponse;
if (data.post.creator_id == UserService.Instance.user.id) {

View file

@ -28,8 +28,17 @@ export const routes: IRoutePropsWithFetch[] = [
component: Main,
},
{ path: `/login`, component: Login },
{ path: `/create_post`, component: CreatePost },
{ path: `/create_community`, component: CreateCommunity },
{
path: `/create_post`,
component: CreatePost,
fetchInitialData: (auth, path) => CreatePost.fetchInitialData(auth, path),
},
{
path: `/create_community`,
component: CreateCommunity,
fetchInitialData: (auth, path) =>
CreateCommunity.fetchInitialData(auth, path),
},
{
path: `/create_private_message`,
component: CreatePrivateMessage,

View file

@ -50,7 +50,10 @@ import { httpUri } from './env';
import { CommentSortType, DataType, IsoData } from './interfaces';
import { UserService, WebSocketService } from './services';
// import Tribute from 'tributejs';
var Tribute;
if (isBrowser()) {
Tribute = require('tributejs');
}
import markdown_it from 'markdown-it';
import markdown_it_sub from 'markdown-it-sub';
import markdown_it_sup from 'markdown-it-sup';
@ -266,6 +269,7 @@ export function isVideo(url: string) {
// TODO this broke
export function validURL(str: string) {
console.log(str);
// try {
return !!new URL(str);
// } catch {
@ -648,71 +652,71 @@ function notify(info: NotifyInfo, router: any) {
}
}
// export function setupTribute(): Tribute<{}> {
// return new Tribute({
// noMatchTemplate: function () {
// return '';
// },
// collection: [
// // Emojis
// {
// trigger: ':',
// menuItemTemplate: (item: any) => {
// let shortName = `:${item.original.key}:`;
// return `${item.original.val} ${shortName}`;
// },
// selectTemplate: (item: any) => {
// return `:${item.original.key}:`;
// },
// values: Object.entries(emojiShortName).map(e => {
// return { key: e[1], val: e[0] };
// }),
// allowSpaces: false,
// autocompleteMode: true,
// // TODO
// // menuItemLimit: mentionDropdownFetchLimit,
// menuShowMinLength: 2,
// },
// // Users
// {
// trigger: '@',
// selectTemplate: (item: any) => {
// let link = item.original.local
// ? `[${item.original.key}](/u/${item.original.name})`
// : `[${item.original.key}](/user/${item.original.id})`;
// return link;
// },
// values: (text: string, cb: any) => {
// userSearch(text, (users: any) => cb(users));
// },
// allowSpaces: false,
// autocompleteMode: true,
// // TODO
// // menuItemLimit: mentionDropdownFetchLimit,
// menuShowMinLength: 2,
// },
export function setupTribute() {
return new Tribute({
noMatchTemplate: function () {
return '';
},
collection: [
// Emojis
{
trigger: ':',
menuItemTemplate: (item: any) => {
let shortName = `:${item.original.key}:`;
return `${item.original.val} ${shortName}`;
},
selectTemplate: (item: any) => {
return `:${item.original.key}:`;
},
values: Object.entries(emojiShortName).map(e => {
return { key: e[1], val: e[0] };
}),
allowSpaces: false,
autocompleteMode: true,
// TODO
// menuItemLimit: mentionDropdownFetchLimit,
menuShowMinLength: 2,
},
// Users
{
trigger: '@',
selectTemplate: (item: any) => {
let link = item.original.local
? `[${item.original.key}](/u/${item.original.name})`
: `[${item.original.key}](/user/${item.original.id})`;
return link;
},
values: (text: string, cb: any) => {
userSearch(text, (users: any) => cb(users));
},
allowSpaces: false,
autocompleteMode: true,
// TODO
// menuItemLimit: mentionDropdownFetchLimit,
menuShowMinLength: 2,
},
// // Communities
// {
// trigger: '!',
// selectTemplate: (item: any) => {
// let link = item.original.local
// ? `[${item.original.key}](/c/${item.original.name})`
// : `[${item.original.key}](/community/${item.original.id})`;
// return link;
// },
// values: (text: string, cb: any) => {
// communitySearch(text, (communities: any) => cb(communities));
// },
// allowSpaces: false,
// autocompleteMode: true,
// // TODO
// // menuItemLimit: mentionDropdownFetchLimit,
// menuShowMinLength: 2,
// },
// ],
// });
// }
// Communities
{
trigger: '!',
selectTemplate: (item: any) => {
let link = item.original.local
? `[${item.original.key}](/c/${item.original.name})`
: `[${item.original.key}](/community/${item.original.id})`;
return link;
},
values: (text: string, cb: any) => {
communitySearch(text, (communities: any) => cb(communities));
},
allowSpaces: false,
autocompleteMode: true,
// TODO
// menuItemLimit: mentionDropdownFetchLimit,
menuShowMinLength: 2,
},
],
});
}
// TODO
// let tippyInstance = tippy('[data-tippy-content]');