mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 17:26:22 +01:00
implement modify for type
This commit is contained in:
@@ -59,7 +59,6 @@ export function getFailure(
|
|||||||
itemId?: string | number
|
itemId?: string | number
|
||||||
) {
|
) {
|
||||||
if (state.failure) {
|
if (state.failure) {
|
||||||
console.log(state.failure);
|
|
||||||
let identifier = actionType;
|
let identifier = actionType;
|
||||||
if (itemId) {
|
if (itemId) {
|
||||||
identifier += "/" + itemId;
|
identifier += "/" + itemId;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
fetchPermissions,
|
fetchPermissions,
|
||||||
getFetchPermissionsFailure,
|
getFetchPermissionsFailure,
|
||||||
isFetchPermissionsPending,
|
isFetchPermissionsPending,
|
||||||
getPermissionsOfRepo
|
getPermissionsOfRepo,
|
||||||
} from "../modules/permissions";
|
} from "../modules/permissions";
|
||||||
import Loading from "../../components/Loading";
|
import Loading from "../../components/Loading";
|
||||||
import ErrorPage from "../../components/ErrorPage";
|
import ErrorPage from "../../components/ErrorPage";
|
||||||
@@ -52,7 +52,13 @@ class Permissions extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (permissions.length > 0)
|
if (permissions.length > 0)
|
||||||
return <PermissionsTable permissions={permissions} namespace={namespace} name={name} />;
|
return (
|
||||||
|
<PermissionsTable
|
||||||
|
permissions={permissions}
|
||||||
|
namespace={namespace}
|
||||||
|
name={name}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return <div />;
|
return <div />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,8 @@ import React from "react";
|
|||||||
import { translate } from "react-i18next";
|
import { translate } from "react-i18next";
|
||||||
import PermissionRow from "../components/table/PermissionRow";
|
import PermissionRow from "../components/table/PermissionRow";
|
||||||
import type { Permission, PermissionCollection } from "../types/Permissions";
|
import type { Permission, PermissionCollection } from "../types/Permissions";
|
||||||
import PermissionRowEditable from "../components/table/PermissionRowEditable";
|
import SinglePermission from "./SinglePermission";
|
||||||
import connect from "react-redux/es/connect/connect";
|
|
||||||
import { modifyPermission } from "../modules/permissions";
|
|
||||||
import type { History } from "history";
|
import type { History } from "history";
|
||||||
import {
|
|
||||||
getModifyRepoFailure,
|
|
||||||
isModifyRepoPending
|
|
||||||
} from "../../repos/modules/repos";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
t: string => string,
|
t: string => string,
|
||||||
@@ -18,12 +12,14 @@ type Props = {
|
|||||||
modifyPermission: (Permission, string, string, () => void) => void,
|
modifyPermission: (Permission, string, string, () => void) => void,
|
||||||
namespace: string,
|
namespace: string,
|
||||||
name: string,
|
name: string,
|
||||||
|
match: any,
|
||||||
history: History
|
history: History
|
||||||
};
|
};
|
||||||
|
|
||||||
class PermissionsTable extends React.Component<Props> {
|
class PermissionsTable extends React.Component<Props> {
|
||||||
permissionsModified = () => {
|
permissionsModified = () => {
|
||||||
const { history, name, namespace } = this.props;
|
const { history, name, namespace } = this.props;
|
||||||
|
console.log(history);
|
||||||
history.push(`/repo/${namespace}/${name}/permissions`);
|
history.push(`/repo/${namespace}/${name}/permissions`);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,17 +39,11 @@ class PermissionsTable extends React.Component<Props> {
|
|||||||
{permissions.map((permission, index) => {
|
{permissions.map((permission, index) => {
|
||||||
if (permission._links.update)
|
if (permission._links.update)
|
||||||
return (
|
return (
|
||||||
<PermissionRowEditable
|
<SinglePermission
|
||||||
key={index}
|
key={index}
|
||||||
|
namespace={namespace}
|
||||||
|
name={name}
|
||||||
permission={permission}
|
permission={permission}
|
||||||
submitForm={permission => {
|
|
||||||
this.props.modifyPermission(
|
|
||||||
permission,
|
|
||||||
namespace,
|
|
||||||
name,
|
|
||||||
this.permissionsModified
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
else return <PermissionRow key={index} permission={permission} />;
|
else return <PermissionRow key={index} permission={permission} />;
|
||||||
@@ -64,21 +54,4 @@ class PermissionsTable extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {};
|
export default translate("permissions")(PermissionsTable);
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
modifyPermission: (
|
|
||||||
permission: Permission,
|
|
||||||
namespace: string,
|
|
||||||
name: string,
|
|
||||||
callback: () => void
|
|
||||||
) => {
|
|
||||||
dispatch(modifyPermission(permission, namespace, name, callback));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(translate("permissions")(PermissionsTable));
|
|
||||||
|
|||||||
@@ -1,22 +1,31 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import type { Permission } from "../../types/Permissions";
|
import type { Permission } from "../types/Permissions";
|
||||||
import { Checkbox, InputField } from "../../../components/forms/index";
|
import { Checkbox } from "../../components/forms/index";
|
||||||
import { DeleteButton, SubmitButton } from "../../../components/buttons/index";
|
import { DeleteButton } from "../../components/buttons/index";
|
||||||
import { translate } from "react-i18next";
|
import { translate } from "react-i18next";
|
||||||
import { Select } from "../../../components/forms/index";
|
import { Select } from "../../components/forms/index";
|
||||||
|
import { modifyPermission } from "../modules/permissions";
|
||||||
|
import connect from "react-redux/es/connect/connect";
|
||||||
|
import { withRouter } from "react-router-dom";
|
||||||
|
import type { History } from "history";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
submitForm: Permission => void,
|
submitForm: Permission => void,
|
||||||
|
modifyPermission: (Permission, string, string) => void,
|
||||||
permission: Permission,
|
permission: Permission,
|
||||||
t: string => string
|
t: string => string,
|
||||||
|
namespace: string,
|
||||||
|
name: string,
|
||||||
|
match: any,
|
||||||
|
history: History
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
permission: Permission
|
permission: Permission
|
||||||
};
|
};
|
||||||
|
|
||||||
class PermissionRowEditable extends React.Component<Props, State> {
|
class SinglePermission extends React.Component<Props, State> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -43,10 +52,7 @@ class PermissionRowEditable extends React.Component<Props, State> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
submit = (event: Event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
this.props.submitForm(this.state.permission);
|
|
||||||
};
|
|
||||||
render() {
|
render() {
|
||||||
const { permission } = this.state;
|
const { permission } = this.state;
|
||||||
const { t } = this.props;
|
const { t } = this.props;
|
||||||
@@ -58,12 +64,7 @@ class PermissionRowEditable extends React.Component<Props, State> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>{permission.name}</td>
|
||||||
<InputField
|
|
||||||
value={permission.name ? permission.name : ""}
|
|
||||||
onChange={this.handleNameChange}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td className="is-hidden-mobile">
|
<td className="is-hidden-mobile">
|
||||||
<Select
|
<Select
|
||||||
onChange={this.handleTypeChange}
|
onChange={this.handleTypeChange}
|
||||||
@@ -72,18 +73,7 @@ class PermissionRowEditable extends React.Component<Props, State> {
|
|||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<Checkbox
|
<Checkbox checked={permission ? permission.groupPermission : false} />
|
||||||
checked={
|
|
||||||
permission.groupPermission ? permission.groupPermission : false
|
|
||||||
}
|
|
||||||
onChange={this.handleGroupPermissionChange}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<SubmitButton
|
|
||||||
label={t("edit-permission.save-button")}
|
|
||||||
action={this.submit}
|
|
||||||
/>
|
|
||||||
</td>
|
</td>
|
||||||
<td>{deleteButton}</td>
|
<td>{deleteButton}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -97,6 +87,17 @@ class PermissionRowEditable extends React.Component<Props, State> {
|
|||||||
type: type
|
type: type
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.modifyPermission(type);
|
||||||
|
};
|
||||||
|
|
||||||
|
modifyPermission = (type: string) => {
|
||||||
|
let permission = this.state.permission;
|
||||||
|
permission.type = type;
|
||||||
|
this.props.modifyPermission(
|
||||||
|
permission,
|
||||||
|
this.props.namespace,
|
||||||
|
this.props.name
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
createSelectOptions(types: string[]) {
|
createSelectOptions(types: string[]) {
|
||||||
@@ -107,24 +108,22 @@ class PermissionRowEditable extends React.Component<Props, State> {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
handleNameChange = (name: string) => {
|
|
||||||
this.setState({
|
|
||||||
permission: {
|
|
||||||
...this.state.permission,
|
|
||||||
name: name
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleGroupPermissionChange = (groupPermission: boolean) => {
|
|
||||||
this.setState({
|
|
||||||
permission: {
|
|
||||||
...this.state.permission,
|
|
||||||
groupPermission: groupPermission
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default translate("permissions")(PermissionRowEditable);
|
const mapStateToProps = (state, ownProps) => {};
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
modifyPermission: (
|
||||||
|
permission: Permission,
|
||||||
|
namespace: string,
|
||||||
|
name: string
|
||||||
|
) => {
|
||||||
|
dispatch(modifyPermission(permission, namespace, name));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(translate("permissions")(withRouter(SinglePermission)));
|
||||||
@@ -98,12 +98,15 @@ export function modifyPermission(
|
|||||||
callback?: () => void
|
callback?: () => void
|
||||||
) {
|
) {
|
||||||
return function(dispatch: any) {
|
return function(dispatch: any) {
|
||||||
dispatch(modifyPermissionPending(permission, namespace, name));
|
dispatch(
|
||||||
|
modifyPermissionPending(permission, namespace, name)
|
||||||
|
);
|
||||||
return apiClient
|
return apiClient
|
||||||
.put(permission._links.update.href, permission, CONTENT_TYPE)
|
.put(permission._links.update.href, permission, CONTENT_TYPE)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
dispatch(modifyPermissionSuccess(permission, namespace, name));
|
dispatch(
|
||||||
|
modifyPermissionSuccess(permission, namespace, name)
|
||||||
|
);
|
||||||
if (callback) {
|
if (callback) {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
@@ -125,7 +128,7 @@ export function modifyPermissionPending(
|
|||||||
return {
|
return {
|
||||||
type: MODIFY_PERMISSION_PENDING,
|
type: MODIFY_PERMISSION_PENDING,
|
||||||
payload: permission,
|
payload: permission,
|
||||||
itemId: namespace + "/" + name
|
itemId: namespace + "/" + name + "/" + permission.name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +139,9 @@ export function modifyPermissionSuccess(
|
|||||||
): Action {
|
): Action {
|
||||||
return {
|
return {
|
||||||
type: MODIFY_PERMISSION_SUCCESS,
|
type: MODIFY_PERMISSION_SUCCESS,
|
||||||
payload: permission,
|
payload: {
|
||||||
|
permission
|
||||||
|
},
|
||||||
itemId: namespace + "/" + name
|
itemId: namespace + "/" + name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -150,16 +155,28 @@ export function modifyPermissionFailure(
|
|||||||
return {
|
return {
|
||||||
type: MODIFY_PERMISSION_FAILURE,
|
type: MODIFY_PERMISSION_FAILURE,
|
||||||
payload: { error, permission },
|
payload: { error, permission },
|
||||||
itemId: namespace + "/" + name
|
itemId: namespace + "/" + name + "/" + permission.name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function newPermissions(modifiedPermission: Permission) {
|
function newPermissions(
|
||||||
let newPermissions = [];
|
oldPermissions: PermissionCollection,
|
||||||
newPermissions[0] = modifiedPermission;
|
newPermission: Permission
|
||||||
return {
|
) {
|
||||||
newPermissions
|
console.log("oldPermissions:");
|
||||||
};
|
console.log(oldPermissions);
|
||||||
|
console.log("new Permission:");
|
||||||
|
console.log(newPermission);
|
||||||
|
for (let i = 0; i < oldPermissions.length; i++) {
|
||||||
|
console.log("permissionname:");
|
||||||
|
console.log("an der stelle i: " + oldPermissions[i].name);
|
||||||
|
if (oldPermissions[i].name === newPermission.name) {
|
||||||
|
oldPermissions.splice(i, 1, newPermission);
|
||||||
|
console.log("new Permissions");
|
||||||
|
console.log(oldPermissions);
|
||||||
|
return oldPermissions;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reducer
|
// reducer
|
||||||
@@ -178,7 +195,10 @@ export default function reducer(
|
|||||||
[action.itemId]: action.payload._embedded.permissions
|
[action.itemId]: action.payload._embedded.permissions
|
||||||
};
|
};
|
||||||
case MODIFY_PERMISSION_SUCCESS:
|
case MODIFY_PERMISSION_SUCCESS:
|
||||||
const newPermission = newPermissions(action.payload);
|
const newPermission = newPermissions(
|
||||||
|
state[action.itemId],
|
||||||
|
action.payload.permission
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
[action.itemId]: newPermission
|
[action.itemId]: newPermission
|
||||||
@@ -216,3 +236,29 @@ export function getFetchPermissionsFailure(
|
|||||||
) {
|
) {
|
||||||
return getFailure(state, FETCH_PERMISSIONS, namespace + "/" + name);
|
return getFailure(state, FETCH_PERMISSIONS, namespace + "/" + name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isModifyPermissionPending(
|
||||||
|
state: Object,
|
||||||
|
namespace: string,
|
||||||
|
name: string,
|
||||||
|
permissionname: string
|
||||||
|
) {
|
||||||
|
return isPending(
|
||||||
|
state,
|
||||||
|
MODIFY_PERMISSION,
|
||||||
|
namespace + "/" + name + "/" + permissionname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getModifyPermissionFailure(
|
||||||
|
state: Object,
|
||||||
|
namespace: string,
|
||||||
|
name: string,
|
||||||
|
permissionname: string
|
||||||
|
) {
|
||||||
|
return getFailure(
|
||||||
|
state,
|
||||||
|
MODIFY_PERMISSION,
|
||||||
|
namespace + "/" + name + "/" + permissionname
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,13 +10,16 @@ import reducer, {
|
|||||||
getFetchPermissionsFailure,
|
getFetchPermissionsFailure,
|
||||||
modifyPermission,
|
modifyPermission,
|
||||||
modifyPermissionSuccess,
|
modifyPermissionSuccess,
|
||||||
|
getModifyPermissionFailure,
|
||||||
|
isModifyPermissionPending,
|
||||||
MODIFY_PERMISSION_FAILURE,
|
MODIFY_PERMISSION_FAILURE,
|
||||||
MODIFY_PERMISSION_PENDING,
|
MODIFY_PERMISSION_PENDING,
|
||||||
FETCH_PERMISSIONS,
|
FETCH_PERMISSIONS,
|
||||||
FETCH_PERMISSIONS_PENDING,
|
FETCH_PERMISSIONS_PENDING,
|
||||||
FETCH_PERMISSIONS_SUCCESS,
|
FETCH_PERMISSIONS_SUCCESS,
|
||||||
FETCH_PERMISSIONS_FAILURE,
|
FETCH_PERMISSIONS_FAILURE,
|
||||||
MODIFY_PERMISSION_SUCCESS
|
MODIFY_PERMISSION_SUCCESS,
|
||||||
|
MODIFY_PERMISSION
|
||||||
} from "./permissions";
|
} from "./permissions";
|
||||||
import type { Permission, PermissionCollection } from "../types/Permissions";
|
import type { Permission, PermissionCollection } from "../types/Permissions";
|
||||||
import { modifyRepoSuccess } from "../../repos/modules/repos";
|
import { modifyRepoSuccess } from "../../repos/modules/repos";
|
||||||
@@ -141,7 +144,14 @@ describe("permission fetch", () => {
|
|||||||
const store = mockStore({});
|
const store = mockStore({});
|
||||||
|
|
||||||
return store
|
return store
|
||||||
.dispatch(modifyPermission(editedPermission, "hitchhiker", "puzzle42"))
|
.dispatch(
|
||||||
|
modifyPermission(
|
||||||
|
editedPermission,
|
||||||
|
"hitchhiker",
|
||||||
|
"puzzle42",
|
||||||
|
"user_eins"
|
||||||
|
)
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const actions = store.getActions();
|
const actions = store.getActions();
|
||||||
expect(actions[0].type).toEqual(MODIFY_PERMISSION_PENDING);
|
expect(actions[0].type).toEqual(MODIFY_PERMISSION_PENDING);
|
||||||
@@ -193,7 +203,14 @@ describe("permission fetch", () => {
|
|||||||
const store = mockStore({});
|
const store = mockStore({});
|
||||||
|
|
||||||
return store
|
return store
|
||||||
.dispatch(modifyPermission(editedPermission, "hitchhiker", "puzzle42"))
|
.dispatch(
|
||||||
|
modifyPermission(
|
||||||
|
editedPermission,
|
||||||
|
"hitchhiker",
|
||||||
|
"puzzle42",
|
||||||
|
"user_eins"
|
||||||
|
)
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const actions = store.getActions();
|
const actions = store.getActions();
|
||||||
expect(actions[0].type).toEqual(MODIFY_PERMISSION_PENDING);
|
expect(actions[0].type).toEqual(MODIFY_PERMISSION_PENDING);
|
||||||
@@ -235,19 +252,20 @@ describe("permissions reducer", () => {
|
|||||||
|
|
||||||
it("should update permission", () => {
|
it("should update permission", () => {
|
||||||
const oldState = {
|
const oldState = {
|
||||||
permissions: {
|
"hitchhiker/puzzle42": [hitchhiker_puzzle42Permission_user_eins]
|
||||||
"hitchhiker/puzzle42": {
|
|
||||||
hitchhiker_puzzle42Permission_user_eins
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let permissionEdited = { ...hitchhiker_puzzle42Permission_user_eins };
|
let permissionEdited = { ...hitchhiker_puzzle42Permission_user_eins };
|
||||||
permissionEdited.type = "OWNER";
|
permissionEdited.type = "OWNER";
|
||||||
|
let expectedState = {
|
||||||
|
"hitchhiker/puzzle42": [permissionEdited]
|
||||||
|
};
|
||||||
const newState = reducer(
|
const newState = reducer(
|
||||||
oldState,
|
oldState,
|
||||||
modifyPermissionSuccess(permissionEdited, "hitchhiker", "puzzle42")
|
modifyPermissionSuccess(permissionEdited, "hitchhiker", "puzzle42")
|
||||||
);
|
);
|
||||||
expect(newState["hitchhiker/puzzle42"]).toEqual(permissionEdited);
|
expect(newState["hitchhiker/puzzle42"]).toEqual(
|
||||||
|
expectedState["hitchhiker/puzzle42"]
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -302,4 +320,38 @@ describe("permissions selectors", () => {
|
|||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return true, when modify permission is pending", () => {
|
||||||
|
const state = {
|
||||||
|
pending: {
|
||||||
|
[MODIFY_PERMISSION + "/hitchhiker/puzzle42/user_eins"]: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(
|
||||||
|
isModifyPermissionPending(state, "hitchhiker", "puzzle42", "user_eins")
|
||||||
|
).toEqual(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return false, when modify permissions is not pending", () => {
|
||||||
|
expect(
|
||||||
|
isModifyPermissionPending({}, "hitchiker", "puzzle42", "user_eins")
|
||||||
|
).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return error when modify permissions did fail", () => {
|
||||||
|
const state = {
|
||||||
|
failure: {
|
||||||
|
[MODIFY_PERMISSION + "/hitchhiker/puzzle42/user_eins"]: error
|
||||||
|
}
|
||||||
|
};
|
||||||
|
expect(
|
||||||
|
getModifyPermissionFailure(state, "hitchhiker", "puzzle42", "user_eins")
|
||||||
|
).toEqual(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return undefined when modify permissions did not fail", () => {
|
||||||
|
expect(
|
||||||
|
getModifyPermissionFailure({}, "hitchhiker", "puzzle42", "user_eins")
|
||||||
|
).toBe(undefined);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user