"eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.1",
"import-sort-style-module": "^6.0.0",
- "lemmy-js-client": "0.17.0-rc.45",
+ "lemmy-js-client": "0.17.0-rc.46",
"lint-staged": "^13.0.3",
"mini-css-extract-plugin": "^2.6.1",
"node-fetch": "^2.6.1",
-import { None, Some } from "@sniptt/monads";
+import { None } from "@sniptt/monads";
import { Component, createRef, linkEvent, RefObject } from "inferno";
import { NavLink } from "inferno-router";
import {
</li>
</ul>
)}
- {this.amAdmin && (
+ {amAdmin() && (
<ul className="navbar-nav ml-1">
<li className="nav-item">
<NavLink
</li>
</ul>
<ul className="navbar-nav my-2">
- {this.amAdmin && (
+ {amAdmin() && (
<li className="nav-item">
<NavLink
to="/admin"
</li>
</ul>
)}
- {this.amAdmin && (
+ {amAdmin() && (
<ul className="navbar-nav my-2">
<li className="nav-item">
<NavLink
);
}
- get amAdmin(): boolean {
- return amAdmin(Some(this.props.siteRes.admins));
- }
-
handleToggleExpandNavbar(i: Navbar) {
i.setState({ expanded: !i.state.expanded });
}
GetReportCountResponse
);
this.setState({
- unreadReportCount: data.post_reports + data.comment_reports,
+ unreadReportCount:
+ data.post_reports +
+ data.comment_reports +
+ data.private_message_reports.unwrapOr(0),
});
this.sendReportUnread();
} else if (op == UserOperation.GetUnreadRegistrationApplicationCount) {
});
WebSocketService.Instance.send(wsClient.getReportCount(reportCountForm));
- if (this.amAdmin) {
+ if (amAdmin()) {
console.log("Fetching applications...");
let applicationCountForm = new GetUnreadRegistrationApplicationCount({
)}
</>
)}
- {amAdmin(Some(this.props.admins)) && (
+ {amAdmin() && (
<li className="list-inline-item">
{!this.props.community_view.community.removed ? (
<button
return (
!this.props.community_view.community.posting_restricted_to_mods ||
amMod(Some(this.props.moderators)) ||
- amAdmin(Some(this.props.admins))
+ amAdmin()
);
}
adminButtons() {
return (
- amAdmin(this.props.admins) && (
+ amAdmin() && (
<ul className="list-inline mb-1 text-muted font-weight-bold">
<li className="list-inline-item-action">
<button
}
get amAdminOrMod(): boolean {
- return (
- amAdmin(Some(this.state.siteRes.admins)) ||
- amMod(this.state.communityMods)
- );
+ return amAdmin() || amMod(this.state.communityMods);
}
modOrAdminText(person: Option<PersonSafe>): string {
PersonMentionResponse,
PersonMentionView,
PostReportResponse,
+ PrivateMessageReportResponse,
PrivateMessageResponse,
PrivateMessagesResponse,
PrivateMessageView,
if (data) {
toast(i18n.t("report_created"));
}
+ } else if (op == UserOperation.CreatePrivateMessageReport) {
+ let data = wsJsonToRes<PrivateMessageReportResponse>(
+ msg,
+ PrivateMessageReportResponse
+ );
+ if (data) {
+ toast(i18n.t("report_created"));
+ }
}
}
ListCommentReportsResponse,
ListPostReports,
ListPostReportsResponse,
+ ListPrivateMessageReports,
+ ListPrivateMessageReportsResponse,
PostReportResponse,
PostReportView,
+ PrivateMessageReportResponse,
+ PrivateMessageReportView,
UserOperation,
wsJsonToRes,
wsUserOp,
import { InitialFetchRequest } from "../../interfaces";
import { UserService, WebSocketService } from "../../services";
import {
+ amAdmin,
auth,
fetchLimit,
isBrowser,
toast,
updateCommentReportRes,
updatePostReportRes,
+ updatePrivateMessageReportRes,
wsClient,
wsSubscribe,
} from "../../utils";
import { Spinner } from "../common/icon";
import { Paginator } from "../common/paginator";
import { PostReport } from "../post/post-report";
+import { PrivateMessageReport } from "../private_message/private-message-report";
enum UnreadOrAll {
Unread,
All,
CommentReport,
PostReport,
+ PrivateMessageReport,
}
enum MessageEnum {
CommentReport,
PostReport,
+ PrivateMessageReport,
}
type ItemType = {
id: number;
type_: MessageEnum;
- view: CommentReportView | PostReportView;
+ view: CommentReportView | PostReportView | PrivateMessageReportView;
published: string;
};
interface ReportsState {
listCommentReportsResponse: Option<ListCommentReportsResponse>;
listPostReportsResponse: Option<ListPostReportsResponse>;
+ listPrivateMessageReportsResponse: Option<ListPrivateMessageReportsResponse>;
unreadOrAll: UnreadOrAll;
messageType: MessageType;
combined: ItemType[];
private isoData = setIsoData(
this.context,
ListCommentReportsResponse,
- ListPostReportsResponse
+ ListPostReportsResponse,
+ ListPrivateMessageReportsResponse
);
private subscription: Subscription;
private emptyState: ReportsState = {
listCommentReportsResponse: None,
listPostReportsResponse: None,
+ listPrivateMessageReportsResponse: None,
unreadOrAll: UnreadOrAll.Unread,
messageType: MessageType.All,
combined: [],
this.isoData.routeData[1] as ListPostReportsResponse
),
};
+ if (amAdmin()) {
+ this.state = {
+ ...this.state,
+ listPrivateMessageReportsResponse: Some(
+ this.isoData.routeData[2] as ListPrivateMessageReportsResponse
+ ),
+ };
+ }
this.state = {
...this.state,
combined: this.buildCombined(),
this.commentReports()}
{this.state.messageType == MessageType.PostReport &&
this.postReports()}
+ {this.state.messageType == MessageType.PrivateMessageReport &&
+ this.privateMessageReports()}
<Paginator
page={this.state.page}
onChange={this.handlePageChange}
/>
{i18n.t("posts")}
</label>
+ {amAdmin() && (
+ <label
+ className={`btn btn-outline-secondary pointer
+ ${
+ this.state.messageType == MessageType.PrivateMessageReport &&
+ "active"
+ }
+ `}
+ >
+ <input
+ type="radio"
+ value={MessageType.PrivateMessageReport}
+ checked={
+ this.state.messageType == MessageType.PrivateMessageReport
+ }
+ onChange={linkEvent(this, this.handleMessageTypeChange)}
+ />
+ {i18n.t("messages")}
+ </label>
+ )}
</div>
);
}
);
}
- replyToReplyType(r: CommentReportView): ItemType {
+ commentReportToItemType(r: CommentReportView): ItemType {
return {
id: r.comment_report.id,
type_: MessageEnum.CommentReport,
};
}
- mentionToReplyType(r: PostReportView): ItemType {
+ postReportToItemType(r: PostReportView): ItemType {
return {
id: r.post_report.id,
type_: MessageEnum.PostReport,
};
}
+ privateMessageReportToItemType(r: PrivateMessageReportView): ItemType {
+ return {
+ id: r.private_message_report.id,
+ type_: MessageEnum.PrivateMessageReport,
+ view: r,
+ published: r.private_message_report.published,
+ };
+ }
+
buildCombined(): ItemType[] {
let comments: ItemType[] = this.state.listCommentReportsResponse
.map(r => r.comment_reports)
.unwrapOr([])
- .map(r => this.replyToReplyType(r));
+ .map(r => this.commentReportToItemType(r));
let posts: ItemType[] = this.state.listPostReportsResponse
.map(r => r.post_reports)
.unwrapOr([])
- .map(r => this.mentionToReplyType(r));
-
- return [...comments, ...posts].sort((a, b) =>
+ .map(r => this.postReportToItemType(r));
+ let privateMessages: ItemType[] =
+ this.state.listPrivateMessageReportsResponse
+ .map(r => r.private_message_reports)
+ .unwrapOr([])
+ .map(r => this.privateMessageReportToItemType(r));
+
+ return [...comments, ...posts, ...privateMessages].sort((a, b) =>
b.published.localeCompare(a.published)
);
}
);
case MessageEnum.PostReport:
return <PostReport key={i.id} report={i.view as PostReportView} />;
+ case MessageEnum.PrivateMessageReport:
+ return (
+ <PrivateMessageReport
+ key={i.id}
+ report={i.view as PrivateMessageReportView}
+ />
+ );
default:
return <div />;
}
});
}
+ privateMessageReports() {
+ return this.state.listPrivateMessageReportsResponse.match({
+ some: res => (
+ <div>
+ {res.private_message_reports.map(pmr => (
+ <>
+ <hr />
+ <PrivateMessageReport
+ key={pmr.private_message_report.id}
+ report={pmr}
+ />
+ </>
+ ))}
+ </div>
+ ),
+ none: <></>,
+ });
+ }
+
handlePageChange(page: number) {
this.setState({ page });
this.refetch();
});
promises.push(req.client.listPostReports(postReportsForm));
+ if (amAdmin()) {
+ let privateMessageReportsForm = new ListPrivateMessageReports({
+ unresolved_only,
+ page,
+ limit,
+ auth,
+ });
+ promises.push(
+ req.client.listPrivateMessageReports(privateMessageReportsForm)
+ );
+ }
+
return promises;
}
auth: auth().unwrap(),
});
WebSocketService.Instance.send(wsClient.listPostReports(postReportsForm));
+
+ if (amAdmin()) {
+ let privateMessageReportsForm = new ListPrivateMessageReports({
+ unresolved_only,
+ page,
+ limit,
+ auth: auth().unwrap(),
+ });
+ WebSocketService.Instance.send(
+ wsClient.listPrivateMessageReports(privateMessageReportsForm)
+ );
+ }
}
parseMessage(msg: any) {
// this.sendUnreadCount();
window.scrollTo(0, 0);
setupTippy();
+ } else if (op == UserOperation.ListPrivateMessageReports) {
+ let data = wsJsonToRes<ListPrivateMessageReportsResponse>(
+ msg,
+ ListPrivateMessageReportsResponse
+ );
+ this.setState({ listPrivateMessageReportsResponse: Some(data) });
+ this.setState({ combined: this.buildCombined(), loading: false });
+ // this.sendUnreadCount();
+ window.scrollTo(0, 0);
+ setupTippy();
} else if (op == UserOperation.ResolvePostReport) {
let data = wsJsonToRes<PostReportResponse>(msg, PostReportResponse);
updatePostReportRes(
urcs.next(urcs.getValue() + 1);
}
this.setState(this.state);
+ } else if (op == UserOperation.ResolvePrivateMessageReport) {
+ let data = wsJsonToRes<PrivateMessageReportResponse>(
+ msg,
+ PrivateMessageReportResponse
+ );
+ updatePrivateMessageReportRes(
+ data.private_message_report_view,
+ this.state.listPrivateMessageReportsResponse
+ .map(r => r.private_message_reports)
+ .unwrapOr([])
+ );
+ let urcs = UserService.Instance.unreadReportCountSub;
+ if (data.private_message_report_view.private_message_report.resolved) {
+ urcs.next(urcs.getValue() - 1);
+ } else {
+ urcs.next(urcs.getValue() + 1);
+ }
+ this.setState(this.state);
}
}
}
--- /dev/null
+import { Component, linkEvent } from "inferno";
+import { T } from "inferno-i18next-dess";
+import {
+ PrivateMessageReportView,
+ ResolvePrivateMessageReport,
+} from "lemmy-js-client";
+import { i18n } from "../../i18next";
+import { WebSocketService } from "../../services";
+import { auth, mdToHtml, wsClient } from "../../utils";
+import { Icon } from "../common/icon";
+import { PersonListing } from "../person/person-listing";
+
+interface Props {
+ report: PrivateMessageReportView;
+}
+
+export class PrivateMessageReport extends Component<Props, any> {
+ constructor(props: any, context: any) {
+ super(props, context);
+ }
+
+ render() {
+ let r = this.props.report;
+ let pmr = r.private_message_report;
+ let tippyContent = i18n.t(
+ r.private_message_report.resolved ? "unresolve_report" : "resolve_report"
+ );
+
+ return (
+ <div>
+ <div>
+ {i18n.t("creator")}:{" "}
+ <PersonListing person={r.private_message_creator} />
+ </div>
+ <div>
+ {i18n.t("message")}:
+ <div
+ className="md-div"
+ dangerouslySetInnerHTML={mdToHtml(pmr.original_pm_text)}
+ />
+ </div>
+ <div>
+ {i18n.t("reporter")}: <PersonListing person={r.creator} />
+ </div>
+ <div>
+ {i18n.t("reason")}: {pmr.reason}
+ </div>
+ {r.resolver.match({
+ some: resolver => (
+ <div>
+ {pmr.resolved ? (
+ <T i18nKey="resolved_by">
+ #
+ <PersonListing person={resolver} />
+ </T>
+ ) : (
+ <T i18nKey="unresolved_by">
+ #
+ <PersonListing person={resolver} />
+ </T>
+ )}
+ </div>
+ ),
+ none: <></>,
+ })}
+ <button
+ className="btn btn-link btn-animate text-muted py-0"
+ onClick={linkEvent(this, this.handleResolveReport)}
+ data-tippy-content={tippyContent}
+ aria-label={tippyContent}
+ >
+ <Icon
+ icon="check"
+ classes={`icon-inline ${
+ pmr.resolved ? "text-success" : "text-danger"
+ }`}
+ />
+ </button>
+ </div>
+ );
+ }
+
+ handleResolveReport(i: PrivateMessageReport) {
+ let pmr = i.props.report.private_message_report;
+ let form = new ResolvePrivateMessageReport({
+ report_id: pmr.id,
+ resolved: !pmr.resolved,
+ auth: auth().unwrap(),
+ });
+ WebSocketService.Instance.send(wsClient.resolvePrivateMessageReport(form));
+ }
+}
-import { None, Some } from "@sniptt/monads/build";
+import { None, Option, Some } from "@sniptt/monads/build";
import { Component, linkEvent } from "inferno";
import {
+ CreatePrivateMessageReport,
DeletePrivateMessage,
MarkPrivateMessageAsRead,
PersonSafe,
PrivateMessageView,
+ toUndefined,
} from "lemmy-js-client";
import { i18n } from "../../i18next";
import { UserService, WebSocketService } from "../../services";
showEdit: boolean;
collapsed: boolean;
viewSource: boolean;
+ showReportDialog: boolean;
+ reportReason: Option<string>;
}
interface PrivateMessageProps {
showEdit: false,
collapsed: false,
viewSource: false,
+ showReportDialog: false,
+ reportReason: None,
};
constructor(props: any, context: any) {
/>
</button>
</li>
+ <li className="list-inline-item">{this.reportButton}</li>
<li className="list-inline-item">
<button
className="btn btn-link btn-animate text-muted"
</div>
)}
</div>
+ {this.state.showReportDialog && (
+ <form
+ className="form-inline"
+ onSubmit={linkEvent(this, this.handleReportSubmit)}
+ >
+ <label className="sr-only" htmlFor="pm-report-reason">
+ {i18n.t("reason")}
+ </label>
+ <input
+ type="text"
+ id="pm-report-reason"
+ className="form-control mr-2"
+ placeholder={i18n.t("reason")}
+ required
+ value={toUndefined(this.state.reportReason)}
+ onInput={linkEvent(this, this.handleReportReasonChange)}
+ />
+ <button
+ type="submit"
+ className="btn btn-secondary"
+ aria-label={i18n.t("create_report")}
+ >
+ {i18n.t("create_report")}
+ </button>
+ </form>
+ )}
{this.state.showReply && (
<PrivateMessageForm
recipient={otherPerson}
);
}
+ get reportButton() {
+ return (
+ <button
+ className="btn btn-link btn-animate text-muted py-0"
+ onClick={linkEvent(this, this.handleShowReportDialog)}
+ data-tippy-content={i18n.t("show_report_dialog")}
+ aria-label={i18n.t("show_report_dialog")}
+ >
+ <Icon icon="flag" inline />
+ </button>
+ );
+ }
+
get messageUnlessRemoved(): string {
let message = this.props.private_message_view.private_message;
return message.deleted ? `*${i18n.t("deleted")}*` : message.content;
i.setState({ viewSource: !i.state.viewSource });
}
+ handleShowReportDialog(i: PrivateMessage) {
+ i.setState({ showReportDialog: !i.state.showReportDialog });
+ }
+
+ handleReportReasonChange(i: PrivateMessage, event: any) {
+ i.setState({ reportReason: Some(event.target.value) });
+ }
+
+ handleReportSubmit(i: PrivateMessage, event: any) {
+ event.preventDefault();
+ let form = new CreatePrivateMessageReport({
+ private_message_id: i.props.private_message_view.private_message.id,
+ reason: toUndefined(i.state.reportReason),
+ auth: auth().unwrap(),
+ });
+ WebSocketService.Instance.send(wsClient.createPrivateMessageReport(form));
+
+ i.setState({ showReportDialog: false });
+ }
+
handlePrivateMessageEdit() {
this.setState({ showEdit: false });
}
PersonViewSafe,
PostReportView,
PostView,
+ PrivateMessageReportView,
PrivateMessageView,
RegistrationApplicationView,
Search,
});
}
-export function amAdmin(
- admins: Option<PersonViewSafe[]>,
- myUserInfo = UserService.Instance.myUserInfo
-): boolean {
- return myUserInfo.match({
- some: mui => isAdmin(admins, mui.local_user_view.person.id),
- none: false,
- });
+export function amAdmin(myUserInfo = UserService.Instance.myUserInfo): boolean {
+ return myUserInfo
+ .map(mui => mui.local_user_view.person.admin)
+ .unwrapOr(false);
}
export function amCommunityCreator(
}
}
+// TODO possible to make these generic?
export function updatePostReportRes(
data: PostReportView,
reports: PostReportView[]
}
}
+export function updatePrivateMessageReportRes(
+ data: PrivateMessageReportView,
+ reports: PrivateMessageReportView[]
+) {
+ let found = reports.find(
+ c => c.private_message_report.id == data.private_message_report.id
+ );
+ if (found) {
+ found.private_message_report = data.private_message_report;
+ }
+}
+
export function updateRegistrationApplicationRes(
data: RegistrationApplicationView,
applications: RegistrationApplicationView[]
);
}
-export function canCreateCommunity(siteRes: GetSiteResponse): boolean {
+export function canCreateCommunity(
+ siteRes: GetSiteResponse,
+ myUserInfo = UserService.Instance.myUserInfo
+): boolean {
let adminOnly = siteRes.site_view
.map(s => s.site.community_creation_admin_only)
.unwrapOr(false);
- return !adminOnly || amAdmin(Some(siteRes.admins));
+ return !adminOnly || amAdmin(myUserInfo);
}
export function isPostBlocked(
dependencies:
ms "2.1.2"
-debuglog@*, debuglog@^1.0.1:
+debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==
is-builtin-module "^3.0.0"
resolve "^1.8.1"
-imurmurhash@*, imurmurhash@^0.1.4:
+imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
dependencies:
invert-kv "^1.0.0"
-lemmy-js-client@0.17.0-rc.45:
- version "0.17.0-rc.45"
- resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.45.tgz#903122b615d5dae10e65abffa1ee6b70b1a3e52c"
- integrity sha512-jPeeDwGgMQHt6rYJfO7lzHQQ63Ox75Ojdihs7DsCUjLOMygantCsM6BD0xtPs3/rYV09zbYeNizKxEjv/wBnRA==
+lemmy-js-client@0.17.0-rc.46:
+ version "0.17.0-rc.46"
+ resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.46.tgz#c2820821ca46394fd17d1045e54c00a04b15700c"
+ integrity sha512-9HqKKsvToSB397ywXpl0jPa7KIhDaULWel0g35CgmfOkylvuTlpF8UZW20vMXr02Br9qvbRf0hRvi9s5uaji+Q==
levn@^0.4.1:
version "0.4.1"
dependencies:
signal-exit "^3.0.2"
-lodash._baseindexof@*:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
- integrity sha512-bSYo8Pc/f0qAkr8fPJydpJjtrHiSynYfYBjtANIgXv5xEf1WlTC63dIDlgu0s9dmTvzRu1+JJTxcIAHe+sH0FQ==
-
lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
lodash._createset "~4.0.0"
lodash._root "~3.0.0"
-lodash._bindcallback@*:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
- integrity sha512-2wlI0JRAGX8WEf4Gm1p/mv/SZ+jLijpj0jyaE/AXeuQphzCgD8ZQW4oSpoN8JAopujOFGU3KMuq7qfHBWlGpjQ==
-
-lodash._cacheindexof@*:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
- integrity sha512-S8dUjWr7SUT/X6TBIQ/OYoCHo1Stu1ZRy6uMUSKqzFnZp5G5RyQizSm6kvxD2Ewyy6AVfMg4AToeZzKfF99T5w==
-
-lodash._createcache@*:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
- integrity sha512-ev5SP+iFpZOugyab/DEUQxUeZP5qyciVTlgQ1f4Vlw7VUcCD8fVnyIqVUEIaoFH9zjAqdgi69KiofzvVmda/ZQ==
- dependencies:
- lodash._getnative "^3.0.0"
-
lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha512-GTkC6YMprrJZCYU3zcqZj+jkXkrXzq3IPBcF/fIPpNEAB4hZEtXU8zp/RwKOvZl43NUmwDbyRk3+ZTbeRdEBXA==
-lodash._getnative@*, lodash._getnative@^3.0.0:
- version "3.9.1"
- resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
- integrity sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==
-
lodash._root@~3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692"
resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==
-lodash.restparam@*:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
- integrity sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==
-
lodash.union@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
isarray "0.0.1"
string_decoder "~0.10.x"
-readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0:
+readdir-scoped-modules@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309"
integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==