mirror of
https://github.com/rjNemo/ticket_manager
synced 2026-06-06 00:36:39 +00:00
User Page
This commit is contained in:
parent
552fe62330
commit
37ce0fb547
12 changed files with 171 additions and 120 deletions
|
|
@ -43,6 +43,7 @@ namespace TicketManager.Controllers
|
|||
return await _context.AppUsers
|
||||
.Include(u => u.Assignments)
|
||||
.ThenInclude(a => a.Project)
|
||||
.ThenInclude(p => p.Tickets)
|
||||
.Include(u => u.Activities)
|
||||
.AsNoTracking()
|
||||
.Select(u => new AppUserDTO(u))
|
||||
|
|
@ -68,6 +69,7 @@ namespace TicketManager.Controllers
|
|||
var user = await _context.AppUsers
|
||||
.Include(u => u.Assignments)
|
||||
.ThenInclude(a => a.Project)
|
||||
.ThenInclude(p => p.Tickets)
|
||||
.Include(u => u.Activities)
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(u => u.Id == id);
|
||||
|
|
@ -80,12 +82,12 @@ namespace TicketManager.Controllers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specific project with Id.
|
||||
/// Updates the specific user with Id.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
///
|
||||
/// PUT: api/v1/Projects/3
|
||||
/// PUT: api/v1/Users/3
|
||||
/// {
|
||||
/// "id": "357727fd-5262-4522-b8a3-38271d43de84",
|
||||
/// "firstName": "Thomas",
|
||||
|
|
@ -97,7 +99,7 @@ namespace TicketManager.Controllers
|
|||
///
|
||||
/// </remarks>
|
||||
/// <response code="204">Request was succesful but no content is changed</response>
|
||||
/// <response code="404">If the required project is null</response>
|
||||
/// <response code="404">If the required User is null</response>
|
||||
[HttpPut("{id}")]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
|
|
@ -129,12 +131,12 @@ namespace TicketManager.Controllers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a project.
|
||||
/// Creates a User.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
///
|
||||
/// POST: api/v1/Projects/
|
||||
/// POST: api/v1/Users/
|
||||
/// {
|
||||
/// "firstName": "Thomas",
|
||||
/// "lastName": "Price",
|
||||
|
|
@ -144,7 +146,7 @@ namespace TicketManager.Controllers
|
|||
/// }
|
||||
///
|
||||
/// </remarks>
|
||||
/// <response code="201">Returns the created project</response>
|
||||
/// <response code="201">Returns the created User</response>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(StatusCodes.Status201Created)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
|
|
@ -174,15 +176,15 @@ namespace TicketManager.Controllers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the project identified by its Id
|
||||
/// Deletes the User identified by its Id
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Sample request:
|
||||
///
|
||||
/// DELETE: api/v1/Projects/5
|
||||
/// DELETE: api/v1/Users/5
|
||||
///
|
||||
/// </remarks>
|
||||
/// <response code="200">Returns the deleted project</response>
|
||||
/// <response code="200">Returns the deleted User</response>
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[HttpDelete("{id}")]
|
||||
|
|
@ -205,6 +207,7 @@ namespace TicketManager.Controllers
|
|||
var user = await _context.AppUsers
|
||||
.Include(u => u.Assignments)
|
||||
.ThenInclude(a => a.Project)
|
||||
.ThenInclude(p => p.Tickets)
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(u => u.Id == id);
|
||||
if (user == null)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,10 @@ namespace TicketManager.Models
|
|||
public List<Ticket> GetTickets()
|
||||
{
|
||||
var tickets = new List<Ticket>();
|
||||
GetProjects().ForEach(p => tickets.Concat(p.Tickets));
|
||||
foreach (var p in GetProjects())
|
||||
{
|
||||
tickets.AddRange(p.Tickets);
|
||||
}
|
||||
return tickets;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,4 +50,5 @@
|
|||
- [<span style="color:red">x</span>] write dtos without circular dependencies.
|
||||
- [ ] use dtoRequest for PutProjects
|
||||
- [ ] render avatarlist after UserModal Update
|
||||
- [ ] Form validators
|
||||
- [x] Form validators
|
||||
- [ ] Azure
|
||||
|
|
|
|||
|
|
@ -1,19 +1,34 @@
|
|||
import { Project } from "../types/Project";
|
||||
import { Ticket } from "../types/Ticket";
|
||||
import { User } from "../types/User";
|
||||
import { Activity } from "../types/Activity";
|
||||
|
||||
export class UserVM {
|
||||
public id: string;
|
||||
public firstName: string;
|
||||
public lastName: string;
|
||||
public fullName: string;
|
||||
public presentation: string;
|
||||
public email: string;
|
||||
public phone: string;
|
||||
public creationDate: string;
|
||||
public picture: string;
|
||||
public projects: Project[];
|
||||
public tickets: Ticket[];
|
||||
public activities: Activity[];
|
||||
|
||||
public constructor(user: User) {
|
||||
this.id = user.id;
|
||||
this.firstName = user.firstName;
|
||||
this.lastName = user.lastName;
|
||||
this.fullName = user.fullName;
|
||||
this.presentation = user.presentation;
|
||||
this.email = user.email;
|
||||
this.phone = user.phone;
|
||||
this.creationDate = user.creationDate;
|
||||
this.picture = user.picture;
|
||||
this.projects = user.projects;
|
||||
this.tickets = user.tickets;
|
||||
this.activities = user.activities;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ interface IProps {
|
|||
title?: string;
|
||||
remainingDays?: string;
|
||||
validateTicket?: (event: MouseEvent) => void;
|
||||
// archiveTicket: (event: MouseEvent) => void;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
export const HorizontalCard: FC<IProps> = ({
|
||||
title,
|
||||
remainingDays,
|
||||
// archiveTicket,
|
||||
link = "#",
|
||||
validateTicket
|
||||
}) => {
|
||||
return (
|
||||
|
|
@ -23,7 +23,7 @@ export const HorizontalCard: FC<IProps> = ({
|
|||
<div className="row">
|
||||
<div className="card-title">
|
||||
<h6>
|
||||
<Link to="#">
|
||||
<Link to={link}>
|
||||
<b>{title ?? "Nothing to do"}</b>
|
||||
</Link>
|
||||
</h6>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import React, { FC, useState, FormEvent } from "react";
|
||||
import { useParams, useRouteMatch } from "react-router-dom";
|
||||
import { useRouteMatch } from "react-router-dom";
|
||||
import { Modal } from "./Modal";
|
||||
import { NewTicketForm } from "./NewTicketForm";
|
||||
import { Ticket } from "../types/Ticket";
|
||||
import { Project } from "../types/Project";
|
||||
import { post } from "../utils/http";
|
||||
import { Constants } from "../utils/Constants";
|
||||
import { HttpResponse } from "../types/HttpResponse";
|
||||
// import { HttpResponse } from "../types/HttpResponse";
|
||||
|
||||
interface IProps {
|
||||
show: boolean;
|
||||
|
|
@ -38,12 +38,9 @@ export const NewTicketModal: FC<IProps> = ({
|
|||
creatorId: "20bf4b2a-7209-4826-96cd-29c2bc937a94",
|
||||
projectId: parseInt(projectId)
|
||||
};
|
||||
// console.log(newTicket);
|
||||
const response: HttpResponse<Ticket> = await post<Ticket>(
|
||||
`${Constants.ticketsURI}`,
|
||||
newTicket
|
||||
);
|
||||
// console.log(response.parsedBody);
|
||||
|
||||
// const response: HttpResponse<Ticket> =
|
||||
await post<Ticket>(`${Constants.ticketsURI}`, newTicket);
|
||||
handleClose();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React, { FC, useState, ChangeEvent, MouseEvent } from "react";
|
||||
import { Ticket } from "../types/Ticket";
|
||||
import { FloatingButton } from "./FloatingButton";
|
||||
import { HorizontalCard } from "./HorizontalCard";
|
||||
import { FilterBar } from "./FilterBar";
|
||||
import { put } from "../utils/http";
|
||||
|
|
@ -17,19 +16,13 @@ export const ProjectList: FC<IProps> = ({ projects }) => {
|
|||
const clearFilterText: (e: MouseEvent) => void = (e: MouseEvent) => {
|
||||
setFilterText("");
|
||||
};
|
||||
// const archiveTicket = () => {};
|
||||
|
||||
const onClick: (e: MouseEvent) => void = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
setShowNew(true);
|
||||
};
|
||||
const handleChange: (e: ChangeEvent<HTMLInputElement>) => void = (
|
||||
e: ChangeEvent<HTMLInputElement>
|
||||
) => {
|
||||
setFilterText(e.target.value);
|
||||
};
|
||||
|
||||
const [showNew, setShowNew] = useState(false);
|
||||
let filteredTickets = projects.filter(
|
||||
t =>
|
||||
t.status !== "Done" &&
|
||||
|
|
@ -39,18 +32,13 @@ export const ProjectList: FC<IProps> = ({ projects }) => {
|
|||
<>
|
||||
<div className="row valign-wrapper">
|
||||
<h3>Projects</h3>
|
||||
<FloatingButton
|
||||
color="indigo lighten-1"
|
||||
size="small"
|
||||
onClick={onClick}
|
||||
/>
|
||||
<FilterBar
|
||||
filterText={filterText}
|
||||
handleChange={handleChange}
|
||||
clearFilterText={clearFilterText}
|
||||
/>
|
||||
</div>
|
||||
<div className="col s12 grey">
|
||||
<div className="col s12 grey lighten-1">
|
||||
<ul>
|
||||
{filteredTickets.length === 0 ? (
|
||||
<HorizontalCard />
|
||||
|
|
@ -60,6 +48,7 @@ export const ProjectList: FC<IProps> = ({ projects }) => {
|
|||
key={t.id}
|
||||
title={t.title}
|
||||
remainingDays={t.endingDate}
|
||||
link={`/projects/${t.id}`}
|
||||
validateTicket={async (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
await put<HttpResponse<Ticket>>(
|
||||
|
|
@ -67,7 +56,6 @@ export const ProjectList: FC<IProps> = ({ projects }) => {
|
|||
{}
|
||||
);
|
||||
}}
|
||||
// archiveTicket={archiveTicket}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,14 @@ import { Project } from "../types/Project";
|
|||
type TicketListProps = {
|
||||
tickets: Ticket[];
|
||||
allProjects: Project[];
|
||||
addButton?: Boolean;
|
||||
};
|
||||
|
||||
export const TicketList: FC<TicketListProps> = ({ tickets, allProjects }) => {
|
||||
export const TicketList: FC<TicketListProps> = ({
|
||||
tickets,
|
||||
allProjects,
|
||||
addButton = true
|
||||
}) => {
|
||||
const [filterText, setFilterText] = useState<string>("");
|
||||
const clearFilterText: (e: MouseEvent) => void = (e: MouseEvent) => {
|
||||
setFilterText("");
|
||||
|
|
@ -47,11 +52,13 @@ export const TicketList: FC<TicketListProps> = ({ tickets, allProjects }) => {
|
|||
allProjects={allProjects}
|
||||
/>
|
||||
<h3>Tickets</h3>
|
||||
<FloatingButton
|
||||
color="indigo lighten-3"
|
||||
size="small"
|
||||
onClick={onClick}
|
||||
/>
|
||||
{addButton && (
|
||||
<FloatingButton
|
||||
color="indigo lighten-3"
|
||||
size="small"
|
||||
onClick={onClick}
|
||||
/>
|
||||
)}
|
||||
<FilterBar
|
||||
filterText={filterText}
|
||||
handleChange={handleChange}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export const UserTabRouter: FC<IProps> = ({ tickets, tabNames, projects }) => {
|
|||
</Route>
|
||||
|
||||
<Route path={`${url}/tickets`}>
|
||||
<TicketList tickets={tickets} allProjects={[]} />
|
||||
<TicketList tickets={tickets} allProjects={[]} addButton={false} />
|
||||
</Route>
|
||||
</div>
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ export const ProjectController: FC = () => {
|
|||
if (hasError) {
|
||||
return <ErrorController error={error} />;
|
||||
}
|
||||
|
||||
const viewModel = new ProjectVM(project, allUsers, allProjects);
|
||||
return isLoading ? <Preloader /> : <ProjectPage viewModel={viewModel} />;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,90 +1,126 @@
|
|||
import React, { FC, useState, useEffect } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { UserPage } from "../pages/UserPage";
|
||||
import { UserVM } from "../VM/UserVM";
|
||||
import { User } from "../types/User";
|
||||
import { AppFile } from "../types/AppFile";
|
||||
import { Activity } from "../types/Activity";
|
||||
import { Ticket } from "../types/Ticket";
|
||||
import { HttpResponse } from "../types/HttpResponse";
|
||||
import { Preloader } from "../components/Preloader";
|
||||
import { get } from "../utils/http";
|
||||
import { Constants } from "../utils/Constants";
|
||||
import { ErrorController } from "./ErrorController";
|
||||
// import { AppFile } from "../types/AppFile";
|
||||
// import { Activity } from "../types/Activity";
|
||||
// import { Ticket } from "../types/Ticket";
|
||||
|
||||
export const UserController: FC = () => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [user, setUser] = useState<User>({} as User);
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const [error, setError] = useState("");
|
||||
const { id } = useParams();
|
||||
|
||||
const user: User = {
|
||||
id: "resldsm,dgd",
|
||||
firstName: "David",
|
||||
lastName: "Whittaker",
|
||||
fullName: "David Whittaker",
|
||||
presentation: "Interface designer and front-end developer",
|
||||
creationDate: new Date().toDateString(),
|
||||
email: "dw@mail.au",
|
||||
phone: "0998765432",
|
||||
picture: require("../images/user_1.jpg"),
|
||||
projects: [
|
||||
{
|
||||
id: 1,
|
||||
title: "Project Title",
|
||||
description: "What is it about",
|
||||
progression: 25,
|
||||
creationDate: new Date().toDateString(),
|
||||
endingDate: "2020-02-17 15:51:02.787373",
|
||||
status: "Todo",
|
||||
manager: {} as User,
|
||||
users: [] as User[],
|
||||
tickets: [] as Ticket[],
|
||||
files: [] as AppFile[],
|
||||
activities: [] as Activity[]
|
||||
async function httpGetUser(id: string): Promise<void> {
|
||||
try {
|
||||
const response: HttpResponse<User> = await get<User>(
|
||||
`${Constants.usersURI}/${id}`
|
||||
);
|
||||
if (response.parsedBody !== undefined) {
|
||||
setUser(response.parsedBody);
|
||||
setIsLoading(false);
|
||||
}
|
||||
],
|
||||
tickets: [
|
||||
{
|
||||
id: 1,
|
||||
title: "Client objective meeting",
|
||||
description: "Client objective meeting",
|
||||
endingDate: "2020-02-17 15:51:02.787373",
|
||||
status: "Done",
|
||||
project: {
|
||||
id: 1,
|
||||
title: "Project Title",
|
||||
description: "What is it about",
|
||||
progression: 25,
|
||||
creationDate: new Date().toDateString(),
|
||||
endingDate: "2020-02-17 15:51:02.787373",
|
||||
status: "Todo",
|
||||
manager: {} as User,
|
||||
users: [] as User[],
|
||||
tickets: [] as Ticket[],
|
||||
files: [] as AppFile[],
|
||||
activities: [] as Activity[]
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "Assemble Outcomes Report for client",
|
||||
description: "Assemble Outcomes Report for client",
|
||||
endingDate: "2020-02-27 15:51:02.787373",
|
||||
status: "To Do",
|
||||
project: {
|
||||
id: 1,
|
||||
title: "Project Title",
|
||||
description: "What is it about",
|
||||
progression: 25,
|
||||
creationDate: new Date().toDateString(),
|
||||
endingDate: "2020-02-17 15:51:02.787373",
|
||||
status: "Todo",
|
||||
manager: {} as User,
|
||||
users: [] as User[],
|
||||
tickets: [] as Ticket[],
|
||||
files: [] as AppFile[],
|
||||
activities: [] as Activity[]
|
||||
}
|
||||
}
|
||||
],
|
||||
activities: []
|
||||
};
|
||||
} catch (ex) {
|
||||
console.error(ex);
|
||||
setHasError(true);
|
||||
setError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// const user: User = {
|
||||
// id: "resldsm,dgd",
|
||||
// firstName: "Ti",
|
||||
// lastName: "Nyny",
|
||||
// fullName: "Nilka Netty Nemo",
|
||||
// presentation: "Woman of my life ❤️❤️❤️",
|
||||
// creationDate: new Date().toDateString(),
|
||||
// email: "dw@mail.au",
|
||||
// phone: "0998765432",
|
||||
// picture: require("../images/user_1.jpg"),
|
||||
// projects: [
|
||||
// {
|
||||
// id: 1,
|
||||
// title: "OP Baby",
|
||||
// description: "What is it about",
|
||||
// progression: 25,
|
||||
// creationDate: new Date().toDateString(),
|
||||
// endingDate: "2020-02-17 15:51:02.787373",
|
||||
// status: "Todo",
|
||||
// manager: {} as User,
|
||||
// users: [] as User[],
|
||||
// tickets: [] as Ticket[],
|
||||
// files: [] as AppFile[],
|
||||
// activities: [] as Activity[]
|
||||
// }
|
||||
// ],
|
||||
// tickets: [
|
||||
// {
|
||||
// id: 1,
|
||||
// title: "Client objective meeting",
|
||||
// description: "Client objective meeting",
|
||||
// endingDate: "2020-02-17 15:51:02.787373",
|
||||
// status: "Done",
|
||||
// project: {
|
||||
// id: 1,
|
||||
// title: "Project Title",
|
||||
// description: "What is it about",
|
||||
// progression: 25,
|
||||
// creationDate: new Date().toDateString(),
|
||||
// endingDate: "2020-02-17 15:51:02.787373",
|
||||
// status: "Todo",
|
||||
// manager: {} as User,
|
||||
// users: [] as User[],
|
||||
// tickets: [] as Ticket[],
|
||||
// files: [] as AppFile[],
|
||||
// activities: [] as Activity[]
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// id: 2,
|
||||
// title: "Assemble Outcomes Report for client",
|
||||
// description: "Assemble Outcomes Report for client",
|
||||
// endingDate: "2020-02-27 15:51:02.787373",
|
||||
// status: "To Do",
|
||||
// project: {
|
||||
// id: 1,
|
||||
// title: "Project Title",
|
||||
// description: "What is it about",
|
||||
// progression: 25,
|
||||
// creationDate: new Date().toDateString(),
|
||||
// endingDate: "2020-02-17 15:51:02.787373",
|
||||
// status: "Todo",
|
||||
// manager: {} as User,
|
||||
// users: [] as User[],
|
||||
// tickets: [] as Ticket[],
|
||||
// files: [] as AppFile[],
|
||||
// activities: [] as Activity[]
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// activities: []
|
||||
// };
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => setIsLoading(false), 1000);
|
||||
});
|
||||
if (id !== undefined) {
|
||||
httpGetUser(id);
|
||||
} else {
|
||||
setHasError(true);
|
||||
setError("Bad Request");
|
||||
}
|
||||
}, [id]);
|
||||
|
||||
if (hasError) {
|
||||
return <ErrorController error={error} />;
|
||||
}
|
||||
|
||||
const viewModel = new UserVM(user);
|
||||
return isLoading ? <Preloader /> : <UserPage viewModel={viewModel} />;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -58,5 +58,5 @@ const headers: Headers = new Headers({
|
|||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
Authorization:
|
||||
"Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik1UWkNSRFEzUkRnd1FUQXlNRFExTmtOQ09UQXlSamhGTURaRU1Ea3pNRGxHUkRrelFqZENSZyJ9.eyJpc3MiOiJodHRwczovL2Rldi1meWpydm9oeC5hdXRoMC5jb20vIiwic3ViIjoiR3dlZTlGUnN3ejNWNE5vZFVRTjJIcjJyQjJTMDI1UmZAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbG9jYWxob3N0OjUwMDEvYXBpL1YxLyIsImlhdCI6MTU4MzI0ODU1NSwiZXhwIjoxNTgzMzM0OTU1LCJhenAiOiJHd2VlOUZSc3d6M1Y0Tm9kVVFOMkhyMnJCMlMwMjVSZiIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.lfgZAwqq3VHNAM1Y33Vj7Jtal6IdN92qWJHwu5T8l-56kBXNC2g1pm6TshRhYDKmedoJmSddjKXClA9eLu1Ve1X8wLj7CbrhZtGNsOcIEStF9icahCy8y2OdP2U6UXJJt9HehwqvwT3JltH_MqyYeJsyMsah3a3rlu6LoEAHNqF4jk8RUxZKjlVJz_iW-tbJ_GoGYrTp_bgvw6IBpgZvJDPGveaA6ms20CoN4zpXaL2ucgtaRbasXfD-z4NDwYN5_9TRPNcf9cuxViZ28CJ66uWxK8BEKysWnABYkh239Q71K2t41hFvQV8ti5l1UKcuqFf_lUGo0wYo9F-MGK6RKA"
|
||||
"Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik1UWkNSRFEzUkRnd1FUQXlNRFExTmtOQ09UQXlSamhGTURaRU1Ea3pNRGxHUkRrelFqZENSZyJ9.eyJpc3MiOiJodHRwczovL2Rldi1meWpydm9oeC5hdXRoMC5jb20vIiwic3ViIjoiR3dlZTlGUnN3ejNWNE5vZFVRTjJIcjJyQjJTMDI1UmZAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8vbG9jYWxob3N0OjUwMDEvYXBpL1YxLyIsImlhdCI6MTU4NDAzNzQyMCwiZXhwIjoxNTg0MTIzODIwLCJhenAiOiJHd2VlOUZSc3d6M1Y0Tm9kVVFOMkhyMnJCMlMwMjVSZiIsImd0eSI6ImNsaWVudC1jcmVkZW50aWFscyJ9.hbn9fRaMYZuvapjCWB0cvwWlEZ6oDoN8nPN8cSkX720VNHYg4JxwVRf4wnf5nOMLUUEIbUudmkBeCZSeW87SQUi41rEHnB9xDXxbVTiEkmyy1yiZUdsDc9Z_hi1nCzKtrbTRmSA6Uo8aHFF2hBGK2_QUcY6hx3Dqx3OYeNbAVx0xjp5OV4XvhVqA9TH3PP_OziJ9NtZAgGzn8pBRlbuTP0ZXL4pXvbcDNcnInx8r5xT_YYxdGqWBgpSqTrfv5t0fUrnjr4ICW49zSBHhA2Nee456c-hlijJ6ufsFcbqegsN7DkFcpWysrY943bIqXJK9XhZlFnz7kBK2nf8culwtmw"
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue