mirror of
https://github.com/LemmyNet/joinlemmy-site.git
synced 2024-11-22 04:11:15 +00:00
Finishing up helper modal.
This commit is contained in:
parent
709612005b
commit
7241dfaedf
11 changed files with 200 additions and 106 deletions
|
@ -1 +1 @@
|
|||
Subproject commit afcb1684e80a42a6fecd6c0cebdf4caa64f92440
|
||||
Subproject commit fd888ab941a2f77e30ebafda065289fa0542d23e
|
|
@ -1 +1 @@
|
|||
Subproject commit b9a566d8376c1ca4d122d63cb921accc3db6c79f
|
||||
Subproject commit d0f3548379e446d2c333e582734bc68f8d684f4d
|
|
@ -19,4 +19,8 @@ const wrapper = (
|
|||
</BrowserRouter>
|
||||
);
|
||||
|
||||
hydrate(wrapper, document.getElementById("root"));
|
||||
const root = document.getElementById("root");
|
||||
|
||||
if (root) {
|
||||
hydrate(wrapper, root);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ export class App extends Component<any, any> {
|
|||
key={path}
|
||||
path={path}
|
||||
exact={exact}
|
||||
render={props => <C {...props} {...rest} />}
|
||||
render={props => C && <C {...props} {...rest} />}
|
||||
/>
|
||||
))}
|
||||
<Route render={props => <NoMatch {...props} />} />
|
||||
|
|
|
@ -32,33 +32,32 @@ export const INSTANCE_HELPERS: InstanceHelper[] = [
|
|||
|
||||
// TODO add i18n strings, Icons
|
||||
// DO this as an interface and const list
|
||||
|
||||
export interface Category {
|
||||
export interface Topic {
|
||||
name: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
export const All_CATEGORY: Category = {
|
||||
name: "all",
|
||||
export const All_TOPIC: Topic = {
|
||||
name: "all_topics",
|
||||
icon: "TBD",
|
||||
};
|
||||
|
||||
export const SPORTS: Category = {
|
||||
export const SPORTS: Topic = {
|
||||
name: "sports",
|
||||
icon: "TBD",
|
||||
};
|
||||
|
||||
export const TECH: Category = {
|
||||
export const TECH: Topic = {
|
||||
name: "tech",
|
||||
icon: "TBD",
|
||||
};
|
||||
|
||||
export const CATEGORIES: Category[] = [All_CATEGORY, TECH, SPORTS];
|
||||
export const TOPICS: Topic[] = [All_TOPIC, TECH, SPORTS];
|
||||
|
||||
export interface RecommendedInstance {
|
||||
domain: string;
|
||||
languages: string[];
|
||||
categories: Category[];
|
||||
topics: Topic[];
|
||||
}
|
||||
|
||||
// TODO fix these up
|
||||
|
@ -66,86 +65,86 @@ export const RECOMMENDED_INSTANCES: RecommendedInstance[] = [
|
|||
{
|
||||
domain: "lemmy.ml",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "lemmy.world",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "lemmy.fmhy.ml",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "discuss.tchncs.de",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "lemm.ee",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "reddthat.com",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "discuss.online",
|
||||
languages: ["en"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "feddit.dk",
|
||||
languages: ["da"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "feddit.de",
|
||||
languages: ["de"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "discuss.tchncs.de",
|
||||
languages: ["de"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
{
|
||||
domain: "feddit.nl",
|
||||
languages: ["nl"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
|
||||
{
|
||||
domain: "lemmy.pt",
|
||||
languages: ["pt"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
|
||||
{
|
||||
domain: "lemmy.eus",
|
||||
languages: ["eu"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
|
||||
{
|
||||
domain: "tabinezumi.net",
|
||||
languages: ["ja"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
|
||||
{
|
||||
domain: "lm.korako.me",
|
||||
languages: ["ja"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
|
||||
{
|
||||
domain: "feddit.it",
|
||||
languages: ["it"],
|
||||
categories: [TECH],
|
||||
topics: [TECH],
|
||||
},
|
||||
];
|
||||
|
|
|
@ -3,16 +3,17 @@ import { Helmet } from "inferno-helmet";
|
|||
import { i18n, LANGUAGES } from "../i18next";
|
||||
import { T } from "inferno-i18next";
|
||||
import { instance_stats } from "../instance_stats";
|
||||
import { languageList, mdToHtml, numToSI } from "../utils";
|
||||
import { getQueryParams, mdToHtml, numToSI } from "../utils";
|
||||
import { Badge, SELECT_CLASSES, TEXT_GRADIENT } from "./common";
|
||||
import {
|
||||
INSTANCE_HELPERS,
|
||||
Category,
|
||||
Topic,
|
||||
RECOMMENDED_INSTANCES,
|
||||
All_CATEGORY,
|
||||
CATEGORIES,
|
||||
All_TOPIC,
|
||||
TOPICS,
|
||||
} from "./instances-definitions";
|
||||
import { Icon } from "./icon";
|
||||
import { I18nKeys } from "i18next";
|
||||
|
||||
const TitleBlock = () => (
|
||||
<div className="flex flex-col items-center pt-16 mb-16">
|
||||
|
@ -64,9 +65,6 @@ interface InstanceCardGridProps {
|
|||
instances: any[];
|
||||
}
|
||||
|
||||
// TODO create the instance picker helper
|
||||
|
||||
// - Language, Categories, and Sort Order (active, random)
|
||||
const InstanceCardGrid = ({ instances }: InstanceCardGridProps) => (
|
||||
<div className="grid md:grid-cols-3 grid-cols-1 gap-4">
|
||||
{instances.map(i => (
|
||||
|
@ -282,23 +280,67 @@ function sortActive(instances: any[]): any[] {
|
|||
}
|
||||
|
||||
interface State {
|
||||
instances: any[];
|
||||
sort: Sort;
|
||||
language: string;
|
||||
category: Category;
|
||||
topic: Topic;
|
||||
scroll: boolean;
|
||||
}
|
||||
|
||||
export class Instances extends Component<any, State> {
|
||||
interface Props {
|
||||
sort: Sort;
|
||||
language: string;
|
||||
topic: Topic;
|
||||
scroll: boolean;
|
||||
}
|
||||
|
||||
function getSortFromQuery(sort?: string): Sort {
|
||||
return SORTS.find(s => s.name == sort) ?? RANDOM_SORT;
|
||||
}
|
||||
|
||||
function getTopicFromQuery(topic?: string): Topic {
|
||||
return TOPICS.find(c => c.name == topic) ?? All_TOPIC;
|
||||
}
|
||||
|
||||
function getInstancesQueryParams() {
|
||||
return getQueryParams<Props>({
|
||||
sort: getSortFromQuery,
|
||||
language: d => d || "all",
|
||||
topic: getTopicFromQuery,
|
||||
scroll: d => !!d,
|
||||
});
|
||||
}
|
||||
|
||||
export class Instances extends Component<Props, State> {
|
||||
state: State = {
|
||||
sort: SORTS[0],
|
||||
language: i18n.language.split("-")[0],
|
||||
category: All_CATEGORY,
|
||||
instances: [],
|
||||
sort: RANDOM_SORT,
|
||||
language: "all",
|
||||
topic: All_TOPIC,
|
||||
scroll: false,
|
||||
};
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
}
|
||||
|
||||
buildInstanceList(): any[] {
|
||||
// Set the filters by the query params if they exist
|
||||
componentDidMount(): void {
|
||||
this.setState(getInstancesQueryParams());
|
||||
this.buildInstanceList();
|
||||
this.scrollToSearch();
|
||||
}
|
||||
|
||||
scrollToSearch() {
|
||||
if (this.state.scroll) {
|
||||
const el = document.getElementById("search")?.offsetTop;
|
||||
if (el) {
|
||||
window.scrollTo({ top: el, behavior: "smooth" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildInstanceList() {
|
||||
let instances = instance_stats.stats.instance_details;
|
||||
const recommended = RECOMMENDED_INSTANCES;
|
||||
|
||||
|
@ -312,26 +354,26 @@ export class Instances extends Component<any, State> {
|
|||
);
|
||||
}
|
||||
|
||||
// Category filter
|
||||
if (this.state.category !== All_CATEGORY) {
|
||||
const categoryRecs = recommended.filter(r =>
|
||||
r.categories.includes(this.state.category),
|
||||
// Topic filter
|
||||
if (this.state.topic !== All_TOPIC) {
|
||||
const topicRecs = recommended.filter(r =>
|
||||
r.topics.includes(this.state.topic),
|
||||
);
|
||||
instances = instances.filter(i =>
|
||||
categoryRecs.map(c => c.domain).includes(i.domain),
|
||||
topicRecs.map(c => c.domain).includes(i.domain),
|
||||
);
|
||||
}
|
||||
|
||||
// Sort
|
||||
if (this.state.sort == SORTS[0]) {
|
||||
if (this.state.sort == RANDOM_SORT) {
|
||||
instances = sortRandom(instances);
|
||||
} else if (this.state.sort == SORTS[1]) {
|
||||
} else if (this.state.sort == MOST_ACTIVE_SORT) {
|
||||
instances = sortActive(instances);
|
||||
} else {
|
||||
instances = sortActive(instances).reverse();
|
||||
}
|
||||
|
||||
return instances;
|
||||
this.setState({ instances });
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -345,18 +387,37 @@ export class Instances extends Component<any, State> {
|
|||
<TitleBlock />
|
||||
<ComparisonBlock />
|
||||
{this.filterAndTitleBlock()}
|
||||
<div className="mt-4">
|
||||
{this.state.instances.length > 0 ? (
|
||||
<InstanceCardGrid
|
||||
title={i18n.t("popular_instances")}
|
||||
instances={this.buildInstanceList()}
|
||||
instances={this.state.instances}
|
||||
/>
|
||||
) : (
|
||||
this.seeAllBtn()
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
seeAllBtn() {
|
||||
return (
|
||||
<div>
|
||||
<p className="text-sm text-gray-300 mb-4">{i18n.t("none_found")}</p>
|
||||
<button
|
||||
className="btn btn-sm btn-secondary text-white normal-case"
|
||||
onClick={linkEvent(this, handleSeeAll)}
|
||||
>
|
||||
{i18n.t("see_all_servers")}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO i18n these
|
||||
filterAndTitleBlock() {
|
||||
return (
|
||||
<div className="my-16">
|
||||
<div id="search" className="mt-16">
|
||||
<div className="flex flex-row flex-wrap gap-4">
|
||||
<div className="flex-none">
|
||||
<SectionTitle title={i18n.t("join_title")} />
|
||||
|
@ -365,20 +426,19 @@ export class Instances extends Component<any, State> {
|
|||
<div className="flex-none">
|
||||
<select
|
||||
className={`${SELECT_CLASSES} mr-2`}
|
||||
value={this.state.category.name}
|
||||
onChange={linkEvent(this, handleCategoryChange)}
|
||||
name="category_select"
|
||||
value={this.state.topic.name}
|
||||
onChange={linkEvent(this, handleTopicChange)}
|
||||
name="topic_select"
|
||||
>
|
||||
<option disabled selected>
|
||||
Category
|
||||
{i18n.t("topic")}
|
||||
</option>
|
||||
{CATEGORIES.map(c => (
|
||||
{TOPICS.map(c => (
|
||||
<option key={c.name} value={c.name}>
|
||||
{c.name}
|
||||
{i18n.t(c.name as I18nKeys)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
<select
|
||||
value={this.state.language}
|
||||
onChange={linkEvent(this, handleLanguageChange)}
|
||||
|
@ -386,11 +446,11 @@ export class Instances extends Component<any, State> {
|
|||
>
|
||||
<option disabled>Languages</option>
|
||||
<option key="all" value="all">
|
||||
all
|
||||
{i18n.t("all_languages")}
|
||||
</option>
|
||||
{languageList().map((language, i) => (
|
||||
<option key={i} value={language}>
|
||||
{LANGUAGES.find(l => l.code.startsWith(language)).name}
|
||||
{LANGUAGES.map((l, i) => (
|
||||
<option key={i} value={l.code}>
|
||||
{l.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
@ -400,10 +460,10 @@ export class Instances extends Component<any, State> {
|
|||
className={SELECT_CLASSES}
|
||||
onChange={linkEvent(this, handleSortChange)}
|
||||
>
|
||||
<option disabled>Sort TODO</option>
|
||||
<option disabled>{i18n.t("sort")}</option>
|
||||
{SORTS.map(s => (
|
||||
<option key={s.name} value={s.name}>
|
||||
{s.name}
|
||||
{i18n.t(s.name as I18nKeys)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
@ -415,13 +475,29 @@ export class Instances extends Component<any, State> {
|
|||
}
|
||||
|
||||
function handleSortChange(i: Instances, event: any) {
|
||||
i.setState({ sort: SORTS.find(s => s.name == event.target.value) });
|
||||
i.setState({
|
||||
sort: SORTS.find(s => s.name == event.target.value) ?? RANDOM_SORT,
|
||||
});
|
||||
i.buildInstanceList();
|
||||
}
|
||||
|
||||
function handleCategoryChange(i: Instances, event: any) {
|
||||
i.setState({ category: CATEGORIES.find(c => c.name == event.target.value) });
|
||||
function handleTopicChange(i: Instances, event: any) {
|
||||
i.setState({
|
||||
topic: TOPICS.find(c => c.name == event.target.value) ?? All_TOPIC,
|
||||
});
|
||||
i.buildInstanceList();
|
||||
}
|
||||
|
||||
function handleLanguageChange(i: Instances, event: any) {
|
||||
i.setState({ language: event.target.value });
|
||||
i.buildInstanceList();
|
||||
}
|
||||
|
||||
function handleSeeAll(i: Instances) {
|
||||
i.setState({
|
||||
sort: RANDOM_SORT,
|
||||
language: "all",
|
||||
topic: All_TOPIC,
|
||||
});
|
||||
i.buildInstanceList();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
SupportDonateBlock,
|
||||
TEXT_GRADIENT,
|
||||
} from "./common";
|
||||
import { InstancePicker } from "./instance-picker";
|
||||
|
||||
const TitleBlock = () => (
|
||||
<div className="py-16 flex flex-col items-center">
|
||||
|
@ -18,9 +19,9 @@ const TitleBlock = () => (
|
|||
<p className={`text-6xl font-bold ${TEXT_GRADIENT}`}>Lemmy</p>
|
||||
<p className="text-3xl font-medium text-center">{i18n.t("lemmy_desc")}</p>
|
||||
</div>
|
||||
<div className="flex flex-row justify-around gap-2">
|
||||
<div className="flex flex-row justify-around gap-4">
|
||||
<JoinServerButton />
|
||||
<RunServerButton />
|
||||
<SeeAllServersButton />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -62,18 +63,18 @@ const CarouselBlock = () => (
|
|||
);
|
||||
|
||||
const JoinServerButton = () => (
|
||||
<Link className="btn btn-primary text-white normal-case" to="/instances">
|
||||
<button
|
||||
className="btn btn-primary text-white normal-case"
|
||||
onClick={() => (document.getElementById("picker") as any).showModal()}
|
||||
>
|
||||
{i18n.t("join_a_server")}
|
||||
</Link>
|
||||
</button>
|
||||
);
|
||||
|
||||
const RunServerButton = () => (
|
||||
<a
|
||||
class="btn btn-secondary text-white normal-case"
|
||||
href={`/docs/administration/administration.html`}
|
||||
>
|
||||
{i18n.t("run_a_server")}
|
||||
</a>
|
||||
const SeeAllServersButton = () => (
|
||||
<Link to="/instances" className="btn btn-secondary text-white normal-case">
|
||||
{i18n.t("see_all_servers")}
|
||||
</Link>
|
||||
);
|
||||
|
||||
const FollowCommunitiesBlock = () => (
|
||||
|
@ -86,7 +87,7 @@ const FollowCommunitiesBlock = () => (
|
|||
>
|
||||
#<span className={TEXT_GRADIENT}>#</span>
|
||||
</T>
|
||||
<p class="text-sm text-gray-300 text-center mb-6">
|
||||
<p className="text-sm text-gray-300 text-center mb-6">
|
||||
{i18n.t("lemmy_long_desc")}
|
||||
</p>
|
||||
<JoinServerButton />
|
||||
|
@ -220,12 +221,12 @@ const DiscussionPlatformBlock = () => (
|
|||
#
|
||||
</a>
|
||||
</T>
|
||||
<Link
|
||||
<a
|
||||
className="btn btn-primary bg-white text-primary normal-case"
|
||||
to="/instances"
|
||||
href={`/docs/administration/administration.html`}
|
||||
>
|
||||
{i18n.t("join_a_server")}
|
||||
</Link>
|
||||
{i18n.t("run_a_server")}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -272,7 +273,7 @@ const MoreFeaturesBlock = () => (
|
|||
</div>
|
||||
}
|
||||
text={
|
||||
<Link class="link link-primary" to="/apps">
|
||||
<Link className="link link-primary" to="/apps">
|
||||
{i18n.t("mobile_apps_for_ios_and_android")}
|
||||
</Link>
|
||||
}
|
||||
|
@ -293,7 +294,7 @@ const MoreFeaturesBlock = () => (
|
|||
}
|
||||
text={
|
||||
<T i18nKey="full_vote_scores">
|
||||
#<code class="text-primary">#</code>#
|
||||
#<code className="text-primary">#</code>#
|
||||
</T>
|
||||
}
|
||||
/>
|
||||
|
@ -309,7 +310,7 @@ const MoreFeaturesBlock = () => (
|
|||
icons={<div>:</div>}
|
||||
text={
|
||||
<T i18nKey="emojis_autocomplete">
|
||||
#<code class="text-primary">#</code>
|
||||
#<code className="text-primary">#</code>
|
||||
</T>
|
||||
}
|
||||
/>
|
||||
|
@ -321,8 +322,8 @@ const MoreFeaturesBlock = () => (
|
|||
}
|
||||
text={
|
||||
<T i18nKey="user_tagging">
|
||||
#<code class="text-primary">#</code>
|
||||
<code class="text-primary">#</code>
|
||||
#<code className="text-primary">#</code>
|
||||
<code className="text-primary">#</code>
|
||||
</T>
|
||||
}
|
||||
/>
|
||||
|
@ -368,11 +369,11 @@ const MoreFeaturesBlock = () => (
|
|||
}
|
||||
text={
|
||||
<T i18nKey="rss_feeds">
|
||||
#<code class="text-primary">#</code>
|
||||
<code class="text-primary">#</code>
|
||||
<code class="text-primary">#</code>
|
||||
<code class="text-primary">#</code>
|
||||
<code class="text-primary">#</code>
|
||||
#<code className="text-primary">#</code>
|
||||
<code className="text-primary">#</code>
|
||||
<code className="text-primary">#</code>
|
||||
<code className="text-primary">#</code>
|
||||
<code className="text-primary">#</code>
|
||||
</T>
|
||||
}
|
||||
/>
|
||||
|
@ -428,6 +429,7 @@ export class Main extends Component<any, any> {
|
|||
const title = i18n.t("lemmy_title");
|
||||
return (
|
||||
<div>
|
||||
<InstancePicker />
|
||||
<Helmet title={title}>
|
||||
<meta property={"title"} content={title} />
|
||||
</Helmet>
|
||||
|
|
|
@ -4,7 +4,6 @@ import { Icon, IconSize } from "./icon";
|
|||
import { i18n, LANGUAGES } from "../i18next";
|
||||
import classNames from "classnames";
|
||||
import { SELECT_CLASSES } from "./common";
|
||||
import { languageList } from "../utils";
|
||||
|
||||
const NavLink = ({ content }) => <li className="text-gray-400">{content}</li>;
|
||||
|
||||
|
@ -52,13 +51,13 @@ export const Navbar = ({ footer = false }) => (
|
|||
onChange={linkEvent(this, handleLanguageChange)}
|
||||
className={SELECT_CLASSES}
|
||||
>
|
||||
{languageList().map((language, i) => (
|
||||
{LANGUAGES.map((l, i) => (
|
||||
<option
|
||||
key={i}
|
||||
value={language}
|
||||
selected={i18n.language.startsWith(language)}
|
||||
value={l.code}
|
||||
selected={i18n.language.startsWith(l.code)}
|
||||
>
|
||||
{LANGUAGES.find(l => l.code.startsWith(language)).name}
|
||||
{l.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
|
|
|
@ -21,7 +21,7 @@ export class NewsItem extends Component<any, any> {
|
|||
get markdown(): string {
|
||||
let title = decodeURIComponent(this.props.match.params.title);
|
||||
title = title.replace(/_/g, " ");
|
||||
return news_md.find(v => v.title == title).markdown;
|
||||
return news_md.find(v => v.title == title)?.markdown ?? "";
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import markdown_it from "markdown-it";
|
||||
import { i18n } from "./i18next";
|
||||
|
||||
let SHORTNUM_SI_FORMAT = new Intl.NumberFormat("en-US", {
|
||||
maximumFractionDigits: 1,
|
||||
|
@ -26,6 +25,20 @@ export function mdToHtml(text: string) {
|
|||
return { __html: md.render(text) };
|
||||
}
|
||||
|
||||
export function languageList() {
|
||||
return Object.keys(i18n.services.resourceStore.data).sort();
|
||||
export function getQueryParams<T extends Record<string, any>>(processors: {
|
||||
[K in keyof T]: (param: string) => T[K];
|
||||
}): T {
|
||||
if (isBrowser()) {
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
return Array.from(Object.entries(processors)).reduce(
|
||||
(acc, [key, process]) => ({
|
||||
...acc,
|
||||
[key]: process(searchParams.get(key)),
|
||||
}),
|
||||
{} as T,
|
||||
);
|
||||
}
|
||||
|
||||
return {} as T;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"pretty": true,
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strictNullChecks": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": true,
|
||||
|
|
Loading…
Reference in a new issue