(feat): data providers init
This commit is contained in:
parent
8fe4d93000
commit
522a9d4a43
39
webapi/ClientApp/src/components/SideWidgets/Categories.tsx
Normal file
39
webapi/ClientApp/src/components/SideWidgets/Categories.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React, { FC } from 'react'
|
||||||
|
import { Card, CardBody, CardHeader, Col, Row } from 'reactstrap'
|
||||||
|
import { CategoryModel } from '../../models'
|
||||||
|
|
||||||
|
interface ICategories {
|
||||||
|
items?: CategoryModel []
|
||||||
|
}
|
||||||
|
|
||||||
|
const Categories: FC<ICategories> = ({
|
||||||
|
items = []
|
||||||
|
}) => {
|
||||||
|
const middleIndex = Math.ceil(items.length / 2)
|
||||||
|
|
||||||
|
const firstHalf = items.splice(0, middleIndex)
|
||||||
|
const secondHalf = items.splice(-middleIndex)
|
||||||
|
|
||||||
|
return <Card className="mb-4">
|
||||||
|
<CardHeader>Categories</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
<Row>
|
||||||
|
|
||||||
|
<Col sm="6">
|
||||||
|
<ul className="list-unstyled mb-0">
|
||||||
|
{firstHalf.map((item, index) => <li key={index}><a href="#!">{item.text}</a></li>)}
|
||||||
|
</ul>
|
||||||
|
</Col>
|
||||||
|
<Col sm="6">
|
||||||
|
<ul className="list-unstyled mb-0">
|
||||||
|
{secondHalf.map((item, index) => <li key={index}><a href="#!">{item.text}</a></li>)}
|
||||||
|
</ul>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Categories
|
||||||
|
}
|
||||||
15
webapi/ClientApp/src/components/SideWidgets/Empty.tsx
Normal file
15
webapi/ClientApp/src/components/SideWidgets/Empty.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React, { FC } from 'react'
|
||||||
|
import { Card, CardBody, CardHeader } from 'reactstrap'
|
||||||
|
|
||||||
|
const Empty : FC = () => {
|
||||||
|
return <Card className="mb-4">
|
||||||
|
<CardHeader></CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Empty
|
||||||
|
}
|
||||||
18
webapi/ClientApp/src/components/SideWidgets/Search.tsx
Normal file
18
webapi/ClientApp/src/components/SideWidgets/Search.tsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React, { FC } from 'react'
|
||||||
|
import { Card, CardBody, CardHeader } from 'reactstrap'
|
||||||
|
|
||||||
|
const Search : FC = () => {
|
||||||
|
return <Card className="mb-4">
|
||||||
|
<CardHeader>Search</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
<div className="input-group">
|
||||||
|
<input className="form-control" type="text" placeholder="Enter search term..." aria-label="Enter search term..." aria-describedby="button-search" />
|
||||||
|
<button className="btn btn-primary" id="button-search" type="button">Go!</button>
|
||||||
|
</div>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Search
|
||||||
|
}
|
||||||
@ -1,59 +1,14 @@
|
|||||||
import React, { FC } from 'react'
|
import { Search } from './Search'
|
||||||
import { Card, CardBody, CardHeader, Col, Row } from 'reactstrap'
|
import { Categories } from './Categories'
|
||||||
import { CategoryModel } from '../../models'
|
import { Empty } from './Empty'
|
||||||
|
|
||||||
|
|
||||||
const Search = () => {
|
|
||||||
return <Card className="mb-4">
|
|
||||||
<CardHeader>Search</CardHeader>
|
|
||||||
<CardBody>
|
|
||||||
<div className="input-group">
|
|
||||||
<input className="form-control" type="text" placeholder="Enter search term..." aria-label="Enter search term..." aria-describedby="button-search" />
|
|
||||||
<button className="btn btn-primary" id="button-search" type="button">Go!</button>
|
|
||||||
</div>
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICategories {
|
|
||||||
items?: CategoryModel []
|
|
||||||
}
|
|
||||||
|
|
||||||
const Categories: FC<ICategories> = ({
|
|
||||||
items = []
|
|
||||||
}) => {
|
|
||||||
const middleIndex = Math.ceil(items.length / 2)
|
|
||||||
|
|
||||||
const firstHalf = items.splice(0, middleIndex)
|
|
||||||
const secondHalf = items.splice(-middleIndex)
|
|
||||||
|
|
||||||
return <Card className="mb-4">
|
|
||||||
<CardHeader>Categories</CardHeader>
|
|
||||||
<CardBody>
|
|
||||||
<Row>
|
|
||||||
|
|
||||||
<Col sm="6">
|
|
||||||
<ul className="list-unstyled mb-0">
|
|
||||||
{firstHalf.map((item, index) => <li key={index}><a href="#!">{item.text}</a></li>)}
|
|
||||||
</ul>
|
|
||||||
</Col>
|
|
||||||
<Col sm="6">
|
|
||||||
<ul className="list-unstyled mb-0">
|
|
||||||
{secondHalf.map((item, index) => <li key={index}><a href="#!">{item.text}</a></li>)}
|
|
||||||
</ul>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
}
|
|
||||||
|
|
||||||
const Empty = () => {
|
|
||||||
return <Card className="mb-4">
|
|
||||||
<CardHeader>Side Widget</CardHeader>
|
|
||||||
<CardBody>
|
|
||||||
You can put anything you want inside of these side widgets. They are easy to use, and feature the Bootstrap 5 card component!
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Search,
|
Search,
|
||||||
|
|||||||
@ -40,6 +40,19 @@ export interface FormItemModel {
|
|||||||
placeHolder?: string,
|
placeHolder?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HeaderLink {
|
||||||
|
[key: string]: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Meta {
|
||||||
|
[key: string]: string
|
||||||
|
}
|
||||||
|
export interface HeaderModel {
|
||||||
|
title: string,
|
||||||
|
link: HeaderLink,
|
||||||
|
meta: Meta
|
||||||
|
}
|
||||||
|
|
||||||
export interface ImageModel {
|
export interface ImageModel {
|
||||||
src: string,
|
src: string,
|
||||||
alt: string
|
alt: string
|
||||||
@ -91,19 +104,3 @@ export interface TestimonialModel {
|
|||||||
text: string,
|
text: string,
|
||||||
reviewer: ReviewerModel
|
reviewer: ReviewerModel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export interface HeaderLink {
|
|
||||||
[key: string]: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Meta {
|
|
||||||
[key: string]: string
|
|
||||||
}
|
|
||||||
export interface HeaderModel {
|
|
||||||
title: string,
|
|
||||||
link: HeaderLink,
|
|
||||||
meta: Meta
|
|
||||||
}
|
|
||||||
@ -188,8 +188,8 @@ const BlogCatalog = () => {
|
|||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg="4">
|
<Col lg="4">
|
||||||
<Search />
|
{/*<Search />
|
||||||
<Categories {...blogCategories} />
|
<Categories {...blogCategories} />*/}
|
||||||
<Empty/>
|
<Empty/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@ -84,7 +84,7 @@ const BlogItem = () => {
|
|||||||
if(blogItemTitle.postedOnBy && blogItem?.author)
|
if(blogItemTitle.postedOnBy && blogItem?.author)
|
||||||
blogItemTitle.postedOnBy = blogItemTitle.postedOnBy?.replace('{nickName}', dateFormat(blogItem.author.nickName))
|
blogItemTitle.postedOnBy = blogItemTitle.postedOnBy?.replace('{nickName}', dateFormat(blogItem.author.nickName))
|
||||||
|
|
||||||
return <Container fluid mt="5">
|
return <Container fluid className="mt-5">
|
||||||
<Row>
|
<Row>
|
||||||
<Col lg="8">
|
<Col lg="8">
|
||||||
|
|
||||||
@ -99,11 +99,7 @@ const BlogItem = () => {
|
|||||||
}} />
|
}} />
|
||||||
</Col>
|
</Col>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Col lg="4">
|
<Col lg="4">
|
||||||
<Search />
|
|
||||||
<Categories />
|
|
||||||
<Empty/>
|
<Empty/>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@ -5,9 +5,9 @@ import { Container } from 'reactstrap'
|
|||||||
import style from './scss/style.module.scss'
|
import style from './scss/style.module.scss'
|
||||||
|
|
||||||
const Checkout = () => {
|
const Checkout = () => {
|
||||||
return <Container fluid className={style.container}>
|
return <Container fluid className={`py-5 ${style.container}`}>
|
||||||
<main>
|
<main>
|
||||||
<div className="py-5 text-center">
|
<div className="text-center">
|
||||||
<img className="d-block mx-auto mb-4" src="../assets/brand/bootstrap-logo.svg" alt="" width="72" height="57" />
|
<img className="d-block mx-auto mb-4" src="../assets/brand/bootstrap-logo.svg" alt="" width="72" height="57" />
|
||||||
<h2>Checkout form</h2>
|
<h2>Checkout form</h2>
|
||||||
<p className="lead">Below is an example form built entirely with Bootstrap’s form controls. Each required form group has a validation state that can be triggered by attempting to submit the form without completing it.</p>
|
<p className="lead">Below is an example form built entirely with Bootstrap’s form controls. Each required form group has a validation state that can be triggered by attempting to submit the form without completing it.</p>
|
||||||
|
|||||||
@ -469,6 +469,7 @@ const unloadedState: ContentState = {
|
|||||||
|
|
||||||
export const reducer: Reducer<ContentState> = (state: ContentState | undefined, incomingAction: Action): ContentState => {
|
export const reducer: Reducer<ContentState> = (state: ContentState | undefined, incomingAction: Action): ContentState => {
|
||||||
if (state === undefined) {
|
if (state === undefined) {
|
||||||
|
console.log(unloadedState)
|
||||||
return unloadedState
|
return unloadedState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,6 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Core.Abstractions.DomainObjects {
|
namespace Core.Abstractions.DomainObjects {
|
||||||
public abstract class DomainObject {
|
public abstract class DomainObjectBase<T> : EquatableBase<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.Abstractions.DomainObjects {
|
||||||
|
public abstract class DomainObjectDocumentBase<T> : DomainObjectBase<T> {
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
5
webapi/Core/Abstractions/DomainObjects/PageBase.cs
Normal file
5
webapi/Core/Abstractions/DomainObjects/PageBase.cs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
namespace Core.Abstractions.DomainObjects {
|
||||||
|
public abstract class PageBase<T> : DomainObjectBase<T> { }
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
namespace Core.Abstractions.DomainObjects {
|
||||||
|
public abstract class PageSectionBase<T> : DomainObjectBase<T> {
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public string? Text { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
8
webapi/Core/Abstractions/DomainObjects/PersonBase.cs
Normal file
8
webapi/Core/Abstractions/DomainObjects/PersonBase.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
using Core.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.Abstractions.DomainObjects {
|
||||||
|
public abstract class PersonBase<T> : DomainObjectBase<T> {
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Image? Image { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,8 +7,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Core.Abstractions.DomainObjects {
|
namespace Core.Abstractions.DomainObjects {
|
||||||
|
|
||||||
public abstract class PostItem : DomainObject {
|
public abstract class PostItemBase<T> : DomainObjectDocumentBase<T> {
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Author / Owner
|
/// Author / Owner
|
||||||
65
webapi/Core/Abstractions/Enumeration.cs
Normal file
65
webapi/Core/Abstractions/Enumeration.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Core.Abstractions {
|
||||||
|
public abstract class Enumeration : IComparable {
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public int Id { get; private set; }
|
||||||
|
|
||||||
|
protected Enumeration(int id, string name) => (Id, Name) = (id, name);
|
||||||
|
|
||||||
|
public override string ToString() => Name;
|
||||||
|
|
||||||
|
public static IEnumerable<T> GetAll<T>() where T : Enumeration =>
|
||||||
|
typeof(T).GetFields(BindingFlags.Public |
|
||||||
|
BindingFlags.Static |
|
||||||
|
BindingFlags.DeclaredOnly)
|
||||||
|
.Select(f => f.GetValue(null))
|
||||||
|
.Cast<T>();
|
||||||
|
|
||||||
|
public override bool Equals(object? obj) {
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (obj is not Enumeration otherValue) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeMatches = GetType().Equals(obj.GetType());
|
||||||
|
var valueMatches = Id.Equals(otherValue.Id);
|
||||||
|
|
||||||
|
return typeMatches && valueMatches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => Id.GetHashCode();
|
||||||
|
|
||||||
|
public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue) {
|
||||||
|
var absoluteDifference = Math.Abs(firstValue.Id - secondValue.Id);
|
||||||
|
return absoluteDifference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T FromValue<T>(int value) where T : Enumeration {
|
||||||
|
var matchingItem = Parse<T, int>(value, "value", item => item.Id == value);
|
||||||
|
return matchingItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static T FromDisplayName<T>(string displayName) where T : Enumeration {
|
||||||
|
var matchingItem = Parse<T, string>(displayName, "display name", item => item.Name == displayName);
|
||||||
|
return matchingItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static T Parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration {
|
||||||
|
var matchingItem = GetAll<T>().FirstOrDefault(predicate);
|
||||||
|
|
||||||
|
if (matchingItem == null)
|
||||||
|
throw new InvalidOperationException($"'{value}' is not a valid {description} in {typeof(T)}");
|
||||||
|
|
||||||
|
return matchingItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int CompareTo(object other) => Id.CompareTo(((Enumeration)other).Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
webapi/Core/Abstractions/EquatableBase.cs
Normal file
18
webapi/Core/Abstractions/EquatableBase.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.Abstractions {
|
||||||
|
public abstract class EquatableBase<T> : IEquatable<T> {
|
||||||
|
public bool Equals(T? other) {
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return GetHashCode() == other.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract override int GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
webapi/Core/DomainObjects/Author.cs
Normal file
16
webapi/Core/DomainObjects/Author.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Author : PersonBase<Author>{
|
||||||
|
public string NickName { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,9 +1,14 @@
|
|||||||
using Core.Abstractions.DomainObjects;
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
namespace Core.DomainObjects {
|
namespace Core.DomainObjects {
|
||||||
internal class BlogItem : PostItem {
|
public class BlogItem : DomainObjectBase<BlogItem> {
|
||||||
|
|
||||||
public int Likes { get; set; }
|
public int? ReadTime { get; set; }
|
||||||
public int ReadingTime { get; set; }
|
|
||||||
|
public int? Likes { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
webapi/Core/DomainObjects/Category.cs
Normal file
13
webapi/Core/DomainObjects/Category.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Category : DomainObjectBase<Category> {
|
||||||
|
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
webapi/Core/DomainObjects/Comment.cs
Normal file
18
webapi/Core/DomainObjects/Comment.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Comment : DomainObjectBase<Comment> {
|
||||||
|
public Author Author { get; set; }
|
||||||
|
public string Text { get; set; }
|
||||||
|
public List<Comment>? Responses { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
webapi/Core/DomainObjects/Documents/BlogItem.cs
Normal file
13
webapi/Core/DomainObjects/Documents/BlogItem.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Documents {
|
||||||
|
public class BlogItem : PostItemBase<BlogItem> {
|
||||||
|
|
||||||
|
public int Likes { get; set; }
|
||||||
|
public int ReadingTime { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
webapi/Core/DomainObjects/Documents/Content.cs
Normal file
34
webapi/Core/DomainObjects/Documents/Content.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using Core.DomainObjects.Pages;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Documents {
|
||||||
|
|
||||||
|
public class Content : DomainObjectDocumentBase<Content> {
|
||||||
|
|
||||||
|
public string SiteName { get; set; }
|
||||||
|
public string SiteUrl { get; set; }
|
||||||
|
|
||||||
|
public Header Header { get; set; }
|
||||||
|
|
||||||
|
public Localization Localization { get; set; }
|
||||||
|
|
||||||
|
public List<Route> Routes { get; set; }
|
||||||
|
public List<Route> AdminRoutes { get; set; }
|
||||||
|
public List<Route> ServiceRoutes { get; set; }
|
||||||
|
|
||||||
|
public List<MenuItem> TopMenu { get; set; }
|
||||||
|
public List<MenuItem> SideMenu { get; set; }
|
||||||
|
|
||||||
|
public HomePage HomePage { get; set; }
|
||||||
|
|
||||||
|
public ShopCatalogPage ShopCatalog { get; set; }
|
||||||
|
public ShopItemPage ShopItem { get; set; }
|
||||||
|
|
||||||
|
public BlogCatalogPage BlogCatalog { get; set; }
|
||||||
|
public BlogItemPage Blogitem { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
webapi/Core/DomainObjects/Documents/ShopItem.cs
Normal file
15
webapi/Core/DomainObjects/Documents/ShopItem.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Documents {
|
||||||
|
public class ShopItem : PostItemBase<ShopItem> {
|
||||||
|
public string Sku { get; set; }
|
||||||
|
public int Rating { get; set; }
|
||||||
|
public int Price { get; set; }
|
||||||
|
public int NewPrice { get; set; }
|
||||||
|
public int Quantity { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,9 +9,7 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Core.DomainObjects {
|
namespace Core.DomainObjects {
|
||||||
|
|
||||||
public class User : DomainObject {
|
public class User : DomainObjectDocumentBase<User> {
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
public string NickName { get; set; }
|
public string NickName { get; set; }
|
||||||
|
|
||||||
public string Hash { get; set; }
|
public string Hash { get; set; }
|
||||||
@ -25,5 +23,9 @@ namespace Core.DomainObjects {
|
|||||||
|
|
||||||
public Address BillingAddress { get; set; }
|
public Address BillingAddress { get; set; }
|
||||||
public Address ShippingAddress { get; set; }
|
public Address ShippingAddress { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
13
webapi/Core/DomainObjects/Feature.cs
Normal file
13
webapi/Core/DomainObjects/Feature.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Feature : DomainObjectBase<Feature> {
|
||||||
|
public string Icon { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
webapi/Core/DomainObjects/FormItem.cs
Normal file
17
webapi/Core/DomainObjects/FormItem.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class FormItem : DomainObjectBase<FormItem> {
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public string? PlaceHolder { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
webapi/Core/DomainObjects/Header.cs
Normal file
16
webapi/Core/DomainObjects/Header.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Header : DomainObjectBase<Header> {
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string> HeaderLink { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string> Meta { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
webapi/Core/DomainObjects/Image.cs
Normal file
12
webapi/Core/DomainObjects/Image.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Image : DomainObjectBase<Image> {
|
||||||
|
public string Src { get; set; }
|
||||||
|
public string Alt { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
webapi/Core/DomainObjects/Link.cs
Normal file
12
webapi/Core/DomainObjects/Link.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Link : DomainObjectBase<Link> {
|
||||||
|
public string Target { get; set; }
|
||||||
|
public string AnchorText { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
webapi/Core/DomainObjects/Localization.cs
Normal file
27
webapi/Core/DomainObjects/Localization.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Localization : DomainObjectBase<Localization> {
|
||||||
|
|
||||||
|
public string TimeZone { get; set; }
|
||||||
|
|
||||||
|
public string Locale { get; set; }
|
||||||
|
|
||||||
|
public string DateFormat { get; set; }
|
||||||
|
|
||||||
|
public string TimeFormat { get; set; }
|
||||||
|
|
||||||
|
public string Currency { get; set; }
|
||||||
|
|
||||||
|
public string CurrencySymobol { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
webapi/Core/DomainObjects/MenuItem.cs
Normal file
15
webapi/Core/DomainObjects/MenuItem.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class MenuItem : DomainObjectBase<MenuItem> {
|
||||||
|
|
||||||
|
public string? Icon { get; set; }
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public string? Target { get; set; }
|
||||||
|
public List<MenuItem>? ChildItems { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
webapi/Core/DomainObjects/PageSections/BlogTitleSection.cs
Normal file
11
webapi/Core/DomainObjects/PageSections/BlogTitleSection.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class BlogTitleSection : PageSectionBase<BlogTitleSection> {
|
||||||
|
public string PostedOnBy { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class CallToActionSection : PageSectionBase<CallToActionSection> {
|
||||||
|
public string PrivacyDisclaimer { get; set; }
|
||||||
|
|
||||||
|
public FormItem Email { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
webapi/Core/DomainObjects/PageSections/CommentsSection.cs
Normal file
16
webapi/Core/DomainObjects/PageSections/CommentsSection.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class CommentsSection : PageSectionBase<CommentsSection> {
|
||||||
|
public string LeaveComment { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class FeaturedBlogSection : PageSectionBase<FeaturedBlogSection> {
|
||||||
|
public string ReadTime { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class FeaturedBologsSection : PageSectionBase<FeaturedBologsSection> {
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
webapi/Core/DomainObjects/PageSections/FeaturesSection.cs
Normal file
11
webapi/Core/DomainObjects/PageSections/FeaturesSection.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class FeaturesSection : PageSectionBase<FeaturesSection> {
|
||||||
|
public List<Feature> Items { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
webapi/Core/DomainObjects/PageSections/ProductSection.cs
Normal file
17
webapi/Core/DomainObjects/PageSections/ProductSection.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class ProductSection : PageSectionBase<ProductSection> {
|
||||||
|
public string AvailableQuantity { get; set; }
|
||||||
|
public string AddToCart { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class RelatedProductsSection : PageSectionBase<RelatedProductsSection> {
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class TestimonialsSection : PageSectionBase<TestimonialsSection> {
|
||||||
|
public List<Testimonial> Items { get; set; }
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
webapi/Core/DomainObjects/PageSections/TitleSection.cs
Normal file
13
webapi/Core/DomainObjects/PageSections/TitleSection.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.PageSections {
|
||||||
|
public class TitleSection : PageSectionBase<TitleSection> {
|
||||||
|
public Image? Image { get; set; }
|
||||||
|
public MenuItem? PrimaryLink { get; set; }
|
||||||
|
public MenuItem? SecondaryLink { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
webapi/Core/DomainObjects/Pages/BlogCatalogPage.cs
Normal file
14
webapi/Core/DomainObjects/Pages/BlogCatalogPage.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using Core.DomainObjects.PageSections;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Pages {
|
||||||
|
public class BlogCatalogPage : PageBase<BlogCatalogPage> {
|
||||||
|
|
||||||
|
public TitleSection TitleSection { get; set; }
|
||||||
|
public FeaturedBlogSection FeaturedBlogSection { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
webapi/Core/DomainObjects/Pages/BlogItemPage.cs
Normal file
13
webapi/Core/DomainObjects/Pages/BlogItemPage.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using Core.DomainObjects.PageSections;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Pages {
|
||||||
|
public class BlogItemPage : PageBase<BlogItemPage> {
|
||||||
|
public BlogTitleSection TitleSection { get; set; }
|
||||||
|
public CommentsSection CommentsSection { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
webapi/Core/DomainObjects/Pages/HomePage.cs
Normal file
17
webapi/Core/DomainObjects/Pages/HomePage.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using Core.DomainObjects.PageSections;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Pages {
|
||||||
|
public class HomePage : PageBase<HomePage> {
|
||||||
|
|
||||||
|
public TitleSection TitleSection { get; set; }
|
||||||
|
public FeaturesSection FeaturesSection { get; set; }
|
||||||
|
public TestimonialsSection TestimonialsSection { get; set; }
|
||||||
|
public FeaturedBologsSection FeaturedBlogsSection { get; set; }
|
||||||
|
public CallToActionSection CallToActionSection { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
webapi/Core/DomainObjects/Pages/ShopCatalogPage.cs
Normal file
12
webapi/Core/DomainObjects/Pages/ShopCatalogPage.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using Core.DomainObjects.PageSections;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Pages {
|
||||||
|
public class ShopCatalogPage : PageBase<ShopCatalogPage> {
|
||||||
|
public TitleSection TitleSection { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
webapi/Core/DomainObjects/Pages/ShopItemPage.cs
Normal file
15
webapi/Core/DomainObjects/Pages/ShopItemPage.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using Core.DomainObjects.PageSections;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects.Pages {
|
||||||
|
public class ShopItemPage : PageBase<ShopItemPage> {
|
||||||
|
|
||||||
|
public ProductSection ProductSection { get; set; }
|
||||||
|
|
||||||
|
public RelatedProductsSection RelatedProductsSection { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
webapi/Core/DomainObjects/Reviewer.cs
Normal file
12
webapi/Core/DomainObjects/Reviewer.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Reviewer : PersonBase<Reviewer> {
|
||||||
|
public string FullName { get; set; }
|
||||||
|
public string Position { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
webapi/Core/DomainObjects/Route.cs
Normal file
14
webapi/Core/DomainObjects/Route.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Route : DomainObjectBase<Route> {
|
||||||
|
|
||||||
|
public string Target { get; set; }
|
||||||
|
public string? Component { get; set; }
|
||||||
|
public List<Route>? ChildRoutes { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,17 +0,0 @@
|
|||||||
using Core.Abstractions;
|
|
||||||
using Core.Abstractions.DomainObjects;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Core.DomainObjects {
|
|
||||||
internal class ShopItem : PostItem {
|
|
||||||
public string Sku { get; set; }
|
|
||||||
public int Rating { get; set; }
|
|
||||||
public int Price { get; set; }
|
|
||||||
public int NewPrice { get; set; }
|
|
||||||
public int Quantity { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
17
webapi/Core/DomainObjects/Testimonial.cs
Normal file
17
webapi/Core/DomainObjects/Testimonial.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Core.DomainObjects {
|
||||||
|
public class Testimonial : DomainObjectBase<Testimonial> {
|
||||||
|
public string Text { get; set; }
|
||||||
|
public Reviewer Reviewer { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode() {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
277
webapi/DataProviders/Abstractions/DataProviderBase.cs
Normal file
277
webapi/DataProviders/Abstractions/DataProviderBase.cs
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
using System.Linq.Expressions;
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
using DomainResults.Common;
|
||||||
|
|
||||||
|
using Core.Abstractions.DomainObjects;
|
||||||
|
|
||||||
|
namespace DataProviders.Abstractions {
|
||||||
|
public abstract class DataProviderBase<T> where T : DomainObjectDocumentBase<T> {
|
||||||
|
|
||||||
|
private protected const string _databaseName = "reactredux";
|
||||||
|
|
||||||
|
private protected readonly ILogger<DataProviderBase<T>> _logger;
|
||||||
|
private protected readonly IMongoClient _client;
|
||||||
|
private protected readonly IIdGenerator _idGenerator;
|
||||||
|
private protected readonly ISessionService _sessionService;
|
||||||
|
|
||||||
|
private protected List<T>? _collection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Main constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="idGenerator"></param>
|
||||||
|
/// <param name="dataProviderUtils"></param>
|
||||||
|
public DataProviderBase(
|
||||||
|
ILogger<DataProviderBase<T>> logger,
|
||||||
|
IMongoClient client,
|
||||||
|
IIdGenerator idGenerator,
|
||||||
|
ISessionService sessionService
|
||||||
|
) {
|
||||||
|
_logger = logger;
|
||||||
|
_client = client;
|
||||||
|
_idGenerator = idGenerator;
|
||||||
|
_sessionService = sessionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Testing constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="logger"></param>
|
||||||
|
/// <param name="collection"></param>
|
||||||
|
public DataProviderBase(
|
||||||
|
ILogger<DataProviderBase<T>> logger,
|
||||||
|
ISessionService sessionService,
|
||||||
|
List<T> collection
|
||||||
|
) {
|
||||||
|
_logger = logger;
|
||||||
|
_sessionService = sessionService;
|
||||||
|
_collection = collection ?? new List<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Insert
|
||||||
|
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName) =>
|
||||||
|
InsertAsync(obj, collectionName).Result;
|
||||||
|
|
||||||
|
private protected (Guid?, IDomainResult) Insert(T obj, string collectionName, Guid sessionId) =>
|
||||||
|
InsertAsync(obj, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName) =>
|
||||||
|
InsertAsyncCore(obj, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> InsertAsync(T obj, string collectionName, Guid sessionId) =>
|
||||||
|
InsertAsyncCore(obj, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region InsertMany
|
||||||
|
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName) =>
|
||||||
|
InsertManyAsync(objList, collectionName).Result;
|
||||||
|
|
||||||
|
private protected (List<Guid>?, IDomainResult) InsertMany(List<T> objList, string collectionName, Guid sessionId) =>
|
||||||
|
InsertManyAsync(objList, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName) =>
|
||||||
|
InsertManyAsyncCore(objList, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<(List<Guid>?, IDomainResult)> InsertManyAsync(List<T> objList, string collectionName, Guid sessionId) =>
|
||||||
|
InsertManyAsyncCore(objList, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Get
|
||||||
|
private protected (List<T>?, IDomainResult) GetWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
GetWithPredicateCore(predicate, collectionName);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Update
|
||||||
|
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
UpdateWithPredicateAsync(obj, predicate, collectionName).Result;
|
||||||
|
|
||||||
|
private protected (Guid?, IDomainResult) UpdateWithPredicate(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
UpdateWithPredicateAsync(obj, predicate, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<(Guid?, IDomainResult)> UpdateWithPredicateAsync(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
UpdateWithPredicateAsyncCore(obj, predicate, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Exists
|
||||||
|
private protected (Guid?, IDomainResult) Exists(Guid id, string collectionName) {
|
||||||
|
var (_resultList, result) = GetWithPredicate(x => x.Id == id, collectionName);
|
||||||
|
|
||||||
|
return (result.Status != DomainOperationStatus.Failed && _resultList != null && _resultList.Count > 0
|
||||||
|
? id
|
||||||
|
:null,
|
||||||
|
result);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Delete
|
||||||
|
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteWithPredicateAsync(predicate, collectionName).Result;
|
||||||
|
|
||||||
|
private protected IDomainResult DeleteWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteWithPredicateAsyncCore(predicate, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region DeleteMany
|
||||||
|
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteManyWithPredicateAsync(predicate, collectionName).Result;
|
||||||
|
|
||||||
|
private protected IDomainResult DeleteManyWithPredicate(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteManyWithPredicateAsync(predicate, collectionName, sessionId).Result;
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName) =>
|
||||||
|
DeleteManyWithPredicateAsyncCore(predicate, collectionName, null);
|
||||||
|
|
||||||
|
private protected Task<IDomainResult> DeleteManyWithPredicateAsync(Expression<Func<T, bool>> predicate, string collectionName, Guid sessionId) =>
|
||||||
|
DeleteManyWithPredicateAsyncCore(predicate, collectionName, sessionId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region Core methods
|
||||||
|
private async protected Task<(Guid?, IDomainResult)> InsertAsyncCore(T obj, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
if (_collection != null) {
|
||||||
|
obj.Id = Guid.NewGuid();
|
||||||
|
_collection.Add(obj);
|
||||||
|
return IDomainResult.Success(obj.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.InsertOneAsync(_sessionService.GetSession(sessionId.Value), obj);
|
||||||
|
else
|
||||||
|
collection.InsertOne(obj);
|
||||||
|
|
||||||
|
return IDomainResult.Success(obj.Id);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<Guid?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(List<Guid>?, IDomainResult)> InsertManyAsyncCore(List<T> objList, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
if (_collection != null) {
|
||||||
|
_collection = _collection.Concat(objList).ToList();
|
||||||
|
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
||||||
|
}
|
||||||
|
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.InsertManyAsync(_sessionService.GetSession(sessionId.Value), objList);
|
||||||
|
else
|
||||||
|
collection.InsertMany(objList);
|
||||||
|
|
||||||
|
return IDomainResult.Success(objList.Select(x => x.Id).ToList());
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<List<Guid>?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private (List<T>?, IDomainResult) GetWithPredicateCore(Expression<Func<T, bool>> predicate, string collectionName) {
|
||||||
|
try {
|
||||||
|
List<T>? result;
|
||||||
|
|
||||||
|
if (_collection != null) {
|
||||||
|
result = _collection?.AsQueryable()
|
||||||
|
.Where(predicate).ToList();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName)
|
||||||
|
.Find(predicate).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result != null
|
||||||
|
? IDomainResult.Success(result)
|
||||||
|
: IDomainResult.NotFound<List<T>?>();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<List<T>?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Guid?, IDomainResult)> UpdateWithPredicateAsyncCore(T obj, Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
if (_collection != null) {
|
||||||
|
// remove element(s) from list
|
||||||
|
foreach (var element in _collection.AsQueryable().Where(predicate))
|
||||||
|
_collection = _collection.Where(x => x.Id != element.Id).ToList();
|
||||||
|
|
||||||
|
// add updated element
|
||||||
|
_collection.Add(obj);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.ReplaceOneAsync(_sessionService.GetSession(sessionId.Value), predicate, obj);
|
||||||
|
else
|
||||||
|
await collection.ReplaceOneAsync(predicate, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IDomainResult.Success(obj.Id);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed<Guid?>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDomainResult> DeleteWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.DeleteOneAsync<T>(_sessionService.GetSession(sessionId.Value), predicate);
|
||||||
|
else
|
||||||
|
await collection.DeleteOneAsync<T>(predicate);
|
||||||
|
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IDomainResult> DeleteManyWithPredicateAsyncCore(Expression<Func<T, bool>> predicate, string collectionName, Guid? sessionId) {
|
||||||
|
try {
|
||||||
|
var collection = _client.GetDatabase(_databaseName).GetCollection<T>(collectionName);
|
||||||
|
|
||||||
|
if (sessionId != null)
|
||||||
|
await collection.DeleteManyAsync(_sessionService.GetSession(sessionId.Value), predicate);
|
||||||
|
else
|
||||||
|
await collection.DeleteManyAsync(predicate);
|
||||||
|
|
||||||
|
return IDomainResult.Success();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
_logger.LogError(ex, "Data provider error");
|
||||||
|
return IDomainResult.Failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
public class BlogDataProvider : IBlogDataProvider {
|
public class BlogDataProvider : IBlogDataProvider {
|
||||||
|
|
||||||
private readonly IDataProvidersConfiguration _configuration;
|
|
||||||
|
|
||||||
public BlogDataProvider(IDataProvidersConfiguration configuration) {
|
|
||||||
_configuration = configuration;
|
public BlogDataProvider() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
39
webapi/DataProviders/ContentDataProvider.cs
Normal file
39
webapi/DataProviders/ContentDataProvider.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using Core.DomainObjects.Documents;
|
||||||
|
using DataProviders.Abstractions;
|
||||||
|
using DomainResults.Common;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DataProviders {
|
||||||
|
|
||||||
|
public interface IContentDataProvider {
|
||||||
|
(Content?, IDomainResult) Get(Guid id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class ContentDataProvider : DataProviderBase<Content>, IContentDataProvider {
|
||||||
|
|
||||||
|
private const string _collectionName = "contents";
|
||||||
|
public ContentDataProvider(
|
||||||
|
ILogger<DataProviderBase<Content>> logger,
|
||||||
|
IMongoClient client,
|
||||||
|
IIdGenerator idGenerator,
|
||||||
|
ISessionService sessionService) : base(logger, client, idGenerator, sessionService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public (Content?, IDomainResult) Get(Guid id) {
|
||||||
|
var (list, result) = GetWithPredicate(x => x.Id == id, _collectionName);
|
||||||
|
|
||||||
|
if (!result.IsSuccess || list == null)
|
||||||
|
return (null, result);
|
||||||
|
|
||||||
|
return (list.First(), result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
72
webapi/DataProviders/Converters/EnumerationSerializer.cs
Normal file
72
webapi/DataProviders/Converters/EnumerationSerializer.cs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.IO;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using Core.Abstractions;
|
||||||
|
|
||||||
|
namespace PecMgr.DataProviders.Converters {
|
||||||
|
|
||||||
|
public class EnumerationSerializer<T> : IBsonSerializer<T> where T : Enumeration {
|
||||||
|
private T Deserialize(IBsonReader reader) => Enumeration.FromValue<T>(BsonSerializer.Deserialize<int>(reader));
|
||||||
|
private void Serialize(IBsonWriter writer, T value) => BsonSerializer.Serialize(writer, value.Id);
|
||||||
|
|
||||||
|
public Type ValueType { get => typeof(T); }
|
||||||
|
|
||||||
|
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader);
|
||||||
|
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => Serialize(context.Writer, (T)value);
|
||||||
|
|
||||||
|
|
||||||
|
T IBsonSerializer<T>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader);
|
||||||
|
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, T value) => Serialize(context.Writer, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EnumerationListSerializer<T> : IBsonSerializer<List<T>>, IBsonArraySerializer where T : Enumeration {
|
||||||
|
private List<T> Deserialize(IBsonReader reader) {
|
||||||
|
var type = reader.GetCurrentBsonType();
|
||||||
|
var response = new List<T>();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case BsonType.Array:
|
||||||
|
reader.ReadStartArray();
|
||||||
|
while (reader.ReadBsonType() != BsonType.EndOfDocument) {
|
||||||
|
response.Add(Enumeration.FromValue<T>(BsonSerializer.Deserialize<int>(reader)));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.ReadEndArray();
|
||||||
|
return response;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"No implementation to deserialize {type}");
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
private void Serialize(IBsonWriter writer, List<T> values) {
|
||||||
|
if (values != null) {
|
||||||
|
writer.WriteStartArray();
|
||||||
|
|
||||||
|
foreach (var value in values) {
|
||||||
|
writer.WriteInt32(value.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type ValueType { get => typeof(List<T>); }
|
||||||
|
|
||||||
|
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader);
|
||||||
|
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value) => Serialize(context.Writer, (List<T>)value);
|
||||||
|
|
||||||
|
List<T> IBsonSerializer<List<T>>.Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) => Deserialize(context.Reader);
|
||||||
|
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, List<T> value) => Serialize(context.Writer, value);
|
||||||
|
|
||||||
|
public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo) {
|
||||||
|
string elementName = null;
|
||||||
|
var serializer = BsonSerializer.LookupSerializer(typeof(string));
|
||||||
|
var nominalType = typeof(string);
|
||||||
|
serializationInfo = new BsonSerializationInfo(elementName, serializer, nominalType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -6,4 +6,15 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="DomainResult.Common" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
|
||||||
|
<PackageReference Include="MongoDB.Driver" Version="2.17.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Core\Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson.Serialization.IdGenerators;
|
||||||
|
|
||||||
|
namespace DataProviders.Extensions
|
||||||
|
{
|
||||||
|
public static class ServiceCollectionExtensions {
|
||||||
|
public static void RegisterDataproviders(this IServiceCollection services, IDataProvidersConfig appSettings) {
|
||||||
|
var config = appSettings.Database;
|
||||||
|
|
||||||
|
services.AddSingleton<IMongoClient>(x => new MongoClient(config.ConnectionString));
|
||||||
|
services.AddSingleton<IIdGenerator, GuidGenerator>();
|
||||||
|
|
||||||
|
services.AddSingleton<ISessionService, SessionService>();
|
||||||
|
|
||||||
|
services.AddSingleton<IContentDataProvider, ContentDataProvider>();
|
||||||
|
|
||||||
|
Mappings.RegisterClassMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
webapi/DataProviders/IDataProvidersConfig.cs
Normal file
28
webapi/DataProviders/IDataProvidersConfig.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace DataProviders {
|
||||||
|
public interface IDataProvidersConfig {
|
||||||
|
public Database Database { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDatabase {
|
||||||
|
|
||||||
|
string ConnectionString { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Database : IDatabase {
|
||||||
|
private string _connectionString;
|
||||||
|
public string ConnectionString {
|
||||||
|
get {
|
||||||
|
var envVar = Environment.GetEnvironmentVariable("DB_CONN");
|
||||||
|
return envVar ?? _connectionString;
|
||||||
|
}
|
||||||
|
|
||||||
|
set => _connectionString = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DataProviders {
|
|
||||||
public interface IDataProvidersConfiguration {
|
|
||||||
public Database Database { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Database {
|
|
||||||
public string ConnectionString { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
24
webapi/DataProviders/Mappings.cs
Normal file
24
webapi/DataProviders/Mappings.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization;
|
||||||
|
using MongoDB.Bson.Serialization.Conventions;
|
||||||
|
using MongoDB.Bson.Serialization.Serializers;
|
||||||
|
|
||||||
|
using DataProviders;
|
||||||
|
|
||||||
|
namespace DataProviders {
|
||||||
|
public class Mappings {
|
||||||
|
|
||||||
|
public static void RegisterClassMap() {
|
||||||
|
ConventionRegistry.Register("MyConventions",
|
||||||
|
new ConventionPack {
|
||||||
|
new CamelCaseElementNameConvention(),
|
||||||
|
new IgnoreIfNullConvention(true)
|
||||||
|
}, type => true);
|
||||||
|
|
||||||
|
// https://kevsoft.net/2020/06/25/storing-guids-as-strings-in-mongodb-with-csharp.html
|
||||||
|
BsonSerializer.RegisterSerializer(new GuidSerializer(BsonType.String));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
83
webapi/DataProviders/SessionService.cs
Normal file
83
webapi/DataProviders/SessionService.cs
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace DataProviders {
|
||||||
|
|
||||||
|
public interface ISessionService {
|
||||||
|
Task<Guid> StartSession();
|
||||||
|
IClientSessionHandle? GetSession(Guid id);
|
||||||
|
void StartTransaction(Guid id);
|
||||||
|
void CommitTransaction(Guid id);
|
||||||
|
void RollbackTransaction(Guid id);
|
||||||
|
void DisposeSession(Guid id);
|
||||||
|
}
|
||||||
|
public class SessionService : ISessionService {
|
||||||
|
|
||||||
|
private readonly ILogger<SessionService> _logger;
|
||||||
|
private readonly IMongoClient _client;
|
||||||
|
private Dictionary<Guid, IClientSessionHandle?> _sessions;
|
||||||
|
|
||||||
|
public SessionService(
|
||||||
|
ILogger<SessionService> logger,
|
||||||
|
IMongoClient client
|
||||||
|
) {
|
||||||
|
_logger = logger;
|
||||||
|
_client = client;
|
||||||
|
_sessions = new Dictionary<Guid, IClientSessionHandle?>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Guid> StartSession() {
|
||||||
|
var sessionId = Guid.NewGuid();
|
||||||
|
|
||||||
|
var session = await _client.StartSessionAsync();
|
||||||
|
|
||||||
|
_sessions.Add(sessionId, session);
|
||||||
|
|
||||||
|
return sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IClientSessionHandle? GetSession(Guid id) {
|
||||||
|
_sessions.TryGetValue(id, out IClientSessionHandle? session);
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StartTransaction(Guid id) {
|
||||||
|
var session = GetSession(id);
|
||||||
|
|
||||||
|
if (session != null)
|
||||||
|
session.StartTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CommitTransaction(Guid id) {
|
||||||
|
var session = GetSession(id);
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
session.CommitTransaction();
|
||||||
|
session.Dispose();
|
||||||
|
|
||||||
|
_sessions.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void RollbackTransaction(Guid id) {
|
||||||
|
var session = GetSession(id);
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
await session.AbortTransactionAsync();
|
||||||
|
session.Dispose();
|
||||||
|
|
||||||
|
_sessions.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisposeSession(Guid id) {
|
||||||
|
var session = GetSession(id);
|
||||||
|
|
||||||
|
if (session != null) {
|
||||||
|
session.Dispose();
|
||||||
|
_sessions.Remove(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace DataProviders {
|
|
||||||
public class SiteSettingsDataProvider {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,8 @@
|
|||||||
namespace WeatherForecast {
|
using DataProviders;
|
||||||
public class Configuration {
|
|
||||||
|
namespace WeatherForecast {
|
||||||
|
public class Configuration : IDataProvidersConfig{
|
||||||
public string Secret { get; set; }
|
public string Secret { get; set; }
|
||||||
|
public Database Database { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
webapi/WeatherForecast/Models/HeaderModel.cs
Normal file
12
webapi/WeatherForecast/Models/HeaderModel.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace WeatherForecast.Models {
|
||||||
|
|
||||||
|
|
||||||
|
public class HeaderModel {
|
||||||
|
public string Title { get; set; }
|
||||||
|
public Dictionary<string, string> HeaderLink { get; set; }
|
||||||
|
|
||||||
|
public Dictionary<string, string> Meta { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -4,6 +4,11 @@ using WeatherForecast.Models.Pages;
|
|||||||
namespace WeatherForecast.Models.Responses {
|
namespace WeatherForecast.Models.Responses {
|
||||||
public class GetContentResponseModel : ResponseModel {
|
public class GetContentResponseModel : ResponseModel {
|
||||||
public string SiteName { get; set; }
|
public string SiteName { get; set; }
|
||||||
|
public string SiteUrl { get; set; }
|
||||||
|
|
||||||
|
public HeaderModel Header { get; set; }
|
||||||
|
|
||||||
|
public LocalizationModel Localization { get; set; }
|
||||||
|
|
||||||
public List<RouteModel> Routes { get; set; }
|
public List<RouteModel> Routes { get; set; }
|
||||||
public List<RouteModel> AdminRoutes { get; set; }
|
public List<RouteModel> AdminRoutes { get; set; }
|
||||||
|
|||||||
12
webapi/WeatherForecast/Services/ContentService.cs
Normal file
12
webapi/WeatherForecast/Services/ContentService.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace WeatherForecast.Services {
|
||||||
|
|
||||||
|
public interface IContentService {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ContentService : IContentService {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Core\Core.csproj" />
|
<ProjectReference Include="..\Core\Core.csproj" />
|
||||||
|
<ProjectReference Include="..\DataProviders\DataProviders.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user