(refactor): image sharp upgrade and dummy image generator created

This commit is contained in:
Maksym Sadovnychyy 2023-03-28 21:04:58 +02:00
parent cdaabb4cd3
commit 5ad87b6d48
44 changed files with 495 additions and 141 deletions

View File

@ -1,2 +1,35 @@
BROWSER=none
REACT_APP_SITEID=404c8232-9048-4519-bfba-6e78dc7005ca
REACT_APP_API=https://localhost:7151/api
REACT_APP_SITEID=404c8232-9048-4519-bfba-6e78dc7005ca
REACT_APP_ACCOUNT=Account
REACT_APP_BLOGITEM=BlogItem
REACT_APP_BLOGITEMS=BlogItems
REACT_APP_BLOGITEMS_FEAUTERED=BlogItems/Featured
REACT_APP_CATEGORYITEM=CategoryItem
REACT_APP_CATEGORYITEMS=CategoryItems
REACT_APP_CONTENT=Content
REACT_APP_DKIM=Dkim
REACT_APP_IMAGE=Image
REACT_APP_IMAGES=Images
REACT_APP_INITIALIZATION=Initialization
REACT_APP_SHOPCARTITEM=ShopCartItem
REACT_APP_SHOPCARTITEMS=ShopCartItems
REACT_APP_SHOPITEM=ShopItem
REACT_APP_SHOPITEMS=ShopItems
REACT_APP_TEMPLATE=Template
REACT_APP_UTILS=Utils
REACT_APP_WeatherForecast=WeatherForecast

View File

@ -37,6 +37,67 @@
<DependentUpon>Dockerfile</DependentUpon>
</Content>
<None Include="Dockerfile" />
<Content Include="src\components\FeatherIcons\icons.json" />
<Content Include="src\components\Loader\scss\animations\ball-beat.scss" />
<Content Include="src\components\Loader\scss\animations\ball-clip-rotate-multiple.scss" />
<Content Include="src\components\Loader\scss\animations\ball-clip-rotate-pulse.scss" />
<Content Include="src\components\Loader\scss\animations\ball-clip-rotate.scss" />
<Content Include="src\components\Loader\scss\animations\ball-grid-beat.scss" />
<Content Include="src\components\Loader\scss\animations\ball-grid-pulse.scss" />
<Content Include="src\components\Loader\scss\animations\ball-pulse-rise.scss" />
<Content Include="src\components\Loader\scss\animations\ball-pulse-round.scss" />
<Content Include="src\components\Loader\scss\animations\ball-pulse-sync.scss" />
<Content Include="src\components\Loader\scss\animations\ball-pulse.scss" />
<Content Include="src\components\Loader\scss\animations\ball-rotate.scss" />
<Content Include="src\components\Loader\scss\animations\ball-scale-multiple.scss" />
<Content Include="src\components\Loader\scss\animations\ball-scale-random.scss" />
<Content Include="src\components\Loader\scss\animations\ball-scale-ripple-multiple.scss" />
<Content Include="src\components\Loader\scss\animations\ball-scale-ripple.scss" />
<Content Include="src\components\Loader\scss\animations\ball-scale.scss" />
<Content Include="src\components\Loader\scss\animations\ball-spin-fade-loader.scss" />
<Content Include="src\components\Loader\scss\animations\ball-spin-loader.scss" />
<Content Include="src\components\Loader\scss\animations\ball-triangle-path.scss" />
<Content Include="src\components\Loader\scss\animations\ball-zig-zag-deflect.scss" />
<Content Include="src\components\Loader\scss\animations\ball-zig-zag.scss" />
<Content Include="src\components\Loader\scss\animations\cube-transition.scss" />
<Content Include="src\components\Loader\scss\animations\line-scale-pulse-out-rapid.scss" />
<Content Include="src\components\Loader\scss\animations\line-scale-pulse-out.scss" />
<Content Include="src\components\Loader\scss\animations\line-scale-random.scss" />
<Content Include="src\components\Loader\scss\animations\line-scale.scss" />
<Content Include="src\components\Loader\scss\animations\line-spin-fade-loader.scss" />
<Content Include="src\components\Loader\scss\animations\pacman.scss" />
<Content Include="src\components\Loader\scss\animations\semi-circle-spin.scss" />
<Content Include="src\components\Loader\scss\animations\square-spin.scss" />
<Content Include="src\components\Loader\scss\animations\triangle-skew-spin.scss" />
<Content Include="src\components\Loader\scss\demo\demo.css" />
<Content Include="src\components\Loader\scss\demo\demo.html" />
<Content Include="src\components\Loader\scss\demo\src\demo.jade" />
<Content Include="src\components\Loader\scss\demo\src\demo.scss" />
<Content Include="src\components\Loader\scss\loaders.scss" />
<Content Include="src\components\Loader\scss\README.md" />
<Content Include="src\components\Loader\scss\_functions.scss" />
<Content Include="src\components\Loader\scss\_mixins.scss" />
<Content Include="src\components\Loader\scss\_variables.scss" />
<Content Include="src\components\ReactFastCompare\index.js" />
<Content Include="src\components\ReactFastCompare\LICENSE" />
<Content Include="src\components\ReactFastCompare\README.md" />
<Content Include="src\components\ReactHelmet\HelmetConstants.js" />
<Content Include="src\components\ReactHelmet\HelmetUtils.js" />
<Content Include="src\components\ReactHelmet\index.js" />
<Content Include="src\components\ReactHelmet\LICENSE" />
<Content Include="src\components\ReactHelmet\README.md" />
<Content Include="src\components\ReactSideEffect\index.js" />
<Content Include="src\components\ReactSideEffect\LICENSE" />
<Content Include="src\components\ReactSideEffect\README.md" />
<Content Include="src\layouts\admin\scss\style.module.scss" />
<Content Include="src\layouts\admin\SideMenu\scss\style.module.scss" />
<Content Include="src\layouts\public\scss\style.module.scss" />
<Content Include="src\layouts\scss\style.scss" />
<Content Include="src\pages\Home\scss\style.module.scss" />
<Content Include="src\pages\Shop\Cart\scss\style.module.scss" />
<Content Include="src\pages\Shop\Checkout\scss\style.module.scss" />
<Content Include="src\pages\Signin\scss\style.scss" />
<Content Include="src\pages\Signup\scss\style.scss" />
<Content Include="tsconfig.json" />
<Content Include="package.json" />
<Content Include="README.md" />
@ -44,19 +105,135 @@
<ItemGroup>
<Folder Include="src\" />
<Folder Include="src\components\" />
<Folder Include="src\components\Comments\" />
<Folder Include="src\components\FeatherIcons\" />
<Folder Include="src\components\FeatherRating\" />
<Folder Include="src\components\Loader\" />
<Folder Include="src\components\Loader\scss\" />
<Folder Include="src\components\Loader\scss\animations\" />
<Folder Include="src\components\Loader\scss\demo\" />
<Folder Include="src\components\Loader\scss\demo\src\" />
<Folder Include="src\components\Pagination\" />
<Folder Include="src\components\ReactFastCompare\" />
<Folder Include="src\components\ReactHelmet\" />
<Folder Include="src\components\ReactSideEffect\" />
<Folder Include="src\components\SideWidgets\" />
<Folder Include="src\enumerations\" />
<Folder Include="src\functions\" />
<Folder Include="src\functions\jwtDecode\" />
<Folder Include="src\layouts\" />
<Folder Include="src\layouts\admin\" />
<Folder Include="src\layouts\admin\NavMenu\" />
<Folder Include="src\layouts\admin\scss\" />
<Folder Include="src\layouts\admin\SideMenu\" />
<Folder Include="src\layouts\admin\SideMenu\scss\" />
<Folder Include="src\layouts\public\" />
<Folder Include="src\layouts\public\Footer\" />
<Folder Include="src\layouts\public\NavMenu\" />
<Folder Include="src\layouts\public\scss\" />
<Folder Include="src\layouts\scss\" />
<Folder Include="src\models\" />
<Folder Include="src\pages\" />
<Folder Include="src\pages\Blog\" />
<Folder Include="src\pages\Blog\Catalog\" />
<Folder Include="src\pages\Blog\Catalog\scss\" />
<Folder Include="src\pages\Blog\Item\" />
<Folder Include="src\pages\Home\" />
<Folder Include="src\pages\Home\scss\" />
<Folder Include="src\pages\Profile\" />
<Folder Include="src\pages\Shop\" />
<Folder Include="src\pages\Shop\Cart\" />
<Folder Include="src\pages\Shop\Cart\scss\" />
<Folder Include="src\pages\Shop\Catalog\" />
<Folder Include="src\pages\Shop\Catalog\scss\" />
<Folder Include="src\pages\Shop\Checkout\" />
<Folder Include="src\pages\Shop\Checkout\scss\" />
<Folder Include="src\pages\Shop\Item\" />
<Folder Include="src\pages\Shop\RelatedProducts\" />
<Folder Include="src\pages\Signin\" />
<Folder Include="src\pages\Signin\scss\" />
<Folder Include="src\pages\Signup\" />
<Folder Include="src\pages\Signup\scss\" />
<Folder Include="src\store\" />
<Folder Include="src\store\reducers\" />
</ItemGroup>
<ItemGroup>
<TypeScriptCompile Include="src\App.test.tsx" />
<TypeScriptCompile Include="src\App.tsx" />
<TypeScriptCompile Include="src\components\Comments\index.tsx" />
<TypeScriptCompile Include="src\components\FeatherIcons\FeatherIcon.tsx" />
<TypeScriptCompile Include="src\components\FeatherIcons\IconInner.tsx" />
<TypeScriptCompile Include="src\components\FeatherIcons\index.tsx" />
<TypeScriptCompile Include="src\components\FeatherRating\index.tsx" />
<TypeScriptCompile Include="src\components\FeatherRating\interfaces.ts" />
<TypeScriptCompile Include="src\components\Loader\index.tsx" />
<TypeScriptCompile Include="src\components\Pagination\index.tsx" />
<TypeScriptCompile Include="src\components\Pagination\utils.ts" />
<TypeScriptCompile Include="src\components\ReactHelmet\Types.ts" />
<TypeScriptCompile Include="src\components\SideWidgets\Categories.tsx" />
<TypeScriptCompile Include="src\components\SideWidgets\Empty.tsx" />
<TypeScriptCompile Include="src\components\SideWidgets\index.tsx" />
<TypeScriptCompile Include="src\components\SideWidgets\Search.tsx" />
<TypeScriptCompile Include="src\enumerations\index.ts" />
<TypeScriptCompile Include="src\functions\dateTimeFormat.ts" />
<TypeScriptCompile Include="src\functions\findRoutes.ts" />
<TypeScriptCompile Include="src\functions\getKeyValue.ts" />
<TypeScriptCompile Include="src\functions\index.ts" />
<TypeScriptCompile Include="src\functions\jwtDecode\atob.ts" />
<TypeScriptCompile Include="src\functions\jwtDecode\base64_url_decode.ts" />
<TypeScriptCompile Include="src\functions\jwtDecode\index.ts" />
<TypeScriptCompile Include="src\index.tsx" />
<TypeScriptCompile Include="src\layouts\admin\index.tsx" />
<TypeScriptCompile Include="src\layouts\admin\NavMenu\index.tsx" />
<TypeScriptCompile Include="src\layouts\admin\SideMenu\index.tsx" />
<TypeScriptCompile Include="src\layouts\index.tsx" />
<TypeScriptCompile Include="src\layouts\interfaces.tsx" />
<TypeScriptCompile Include="src\layouts\public\Footer\index.tsx" />
<TypeScriptCompile Include="src\layouts\public\index.tsx" />
<TypeScriptCompile Include="src\layouts\public\NavMenu\index.tsx" />
<TypeScriptCompile Include="src\models\abstractions.ts" />
<TypeScriptCompile Include="src\models\index.ts" />
<TypeScriptCompile Include="src\models\pages.ts" />
<TypeScriptCompile Include="src\models\pageSections.ts" />
<TypeScriptCompile Include="src\models\requests.ts" />
<TypeScriptCompile Include="src\models\responses.ts" />
<TypeScriptCompile Include="src\pages\AdminHome.tsx" />
<TypeScriptCompile Include="src\pages\Blog\Catalog\index.tsx" />
<TypeScriptCompile Include="src\pages\Blog\index.ts" />
<TypeScriptCompile Include="src\pages\Blog\Item\index.tsx" />
<TypeScriptCompile Include="src\pages\Counter.tsx" />
<TypeScriptCompile Include="src\pages\FetchData.tsx" />
<TypeScriptCompile Include="src\pages\Home\index.tsx" />
<TypeScriptCompile Include="src\pages\index.tsx" />
<TypeScriptCompile Include="src\pages\Profile\index.tsx" />
<TypeScriptCompile Include="src\pages\Shop\Cart\index.tsx" />
<TypeScriptCompile Include="src\pages\Shop\Catalog\index.tsx" />
<TypeScriptCompile Include="src\pages\Shop\Checkout\index.tsx" />
<TypeScriptCompile Include="src\pages\Shop\index.ts" />
<TypeScriptCompile Include="src\pages\Shop\Item\index.tsx" />
<TypeScriptCompile Include="src\pages\Shop\RelatedProducts\index.tsx" />
<TypeScriptCompile Include="src\pages\Signin\index.tsx" />
<TypeScriptCompile Include="src\pages\Signup\index.tsx" />
<TypeScriptCompile Include="src\react-app-env.d.ts" />
<TypeScriptCompile Include="src\registerServiceWorker.ts" />
<TypeScriptCompile Include="src\restClient.ts" />
<TypeScriptCompile Include="src\store\configureStore.ts" />
<TypeScriptCompile Include="src\store\index.ts" />
<TypeScriptCompile Include="src\store\reducers\BlogCatalog.ts" />
<TypeScriptCompile Include="src\store\reducers\BlogCategories.ts" />
<TypeScriptCompile Include="src\store\reducers\BlogFeatured.ts" />
<TypeScriptCompile Include="src\store\reducers\BlogItem.ts" />
<TypeScriptCompile Include="src\store\reducers\Content.ts" />
<TypeScriptCompile Include="src\store\reducers\Counter.ts" />
<TypeScriptCompile Include="src\store\reducers\Header.ts" />
<TypeScriptCompile Include="src\store\reducers\Loader.ts" />
<TypeScriptCompile Include="src\store\reducers\ShopCart.ts" />
<TypeScriptCompile Include="src\store\reducers\ShopCatalog.ts" />
<TypeScriptCompile Include="src\store\reducers\ShopCategories.ts" />
<TypeScriptCompile Include="src\store\reducers\ShopFeatured.ts" />
<TypeScriptCompile Include="src\store\reducers\ShopItem.ts" />
<TypeScriptCompile Include="src\store\reducers\ShopRelated.ts" />
<TypeScriptCompile Include="src\store\reducers\WeatherForecasts.ts" />
</ItemGroup>
<Import Project="$(VSToolsPath)\Node.js Tools\Microsoft.NodejsToolsV2.targets" />
<ProjectExtensions>

View File

@ -1,21 +1,19 @@
#Depending on the operating system of the host machines(s) that will build or run the containers, the image specified in the FROM statement may need to be changed.
#For more information, please see https://aka.ms/containercompat
FROM node:16 AS base
# ==== CONFIGURE =====
# Use a Node 16 base image
FROM node:16-alpine
# Set the working directory to /app inside the container
WORKDIR /app
EXPOSE 80
EXPOSE 443
FROM node:16 AS build
WORKDIR /src
COPY ["ClientApp/package.json", "ClientApp/"]
WORKDIR "/src/ClientApp"
# Copy app files
COPY . .
RUN npm install
RUN npm install --location=global react-scripts
#FROM base AS final
#WORKDIR "/src/ClientApp"
#COPY --from=build /app/publish .
ENTRYPOINT ["npm", "run", "start"]
# ==== BUILD =====
# Install dependencies (npm ci makes sure the exact versions in the lockfile gets installed)
RUN npm ci
# Build the app
RUN npm run build
# ==== RUN =======
# Set the env to "production"
ENV NODE_ENV production
# Expose the port on which the app will be running (3000 is the default that `serve` uses)
EXPOSE 3000
# Start the app
CMD [ "npx", "serve", "build" ]

View File

@ -45,7 +45,7 @@ const App = () => {
const { content, header, loader } = useSelector((state: ApplicationState) => state)
useEffect(() => {
dispatch(settingsActionCreators.requestContent({ searchParams: { locale: "en-US" }}))
dispatch(settingsActionCreators.requestContent())
}, [])
useEffect(() => {

View File

@ -49,7 +49,7 @@ const FeaturedBlogSection: FC<FeaturedBlog> = ({
badges: [],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "",
@ -58,7 +58,7 @@ const FeaturedBlogSection: FC<FeaturedBlog> = ({
id: "",
nickName: "",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},

View File

@ -44,7 +44,7 @@ const TitleSection : FC<TitleSectionModel> = ({
</div>
</div>
</Col>
<div className="col-xl-5 col-xxl-6 d-none d-xl-block text-center"><img className="img-fluid rounded-3 my-5" src="https://dummyimage.com/600x400/343a40/6c757d" alt="..." /></div>
<div className="col-xl-5 col-xxl-6 d-none d-xl-block text-center"><img className="img-fluid rounded-3 my-5" src={`${process.env.REACT_APP_API}/Image/600x400/343a40/6c757d`} alt="..." /></div>
</Row>
</Container>
</header>

View File

@ -105,7 +105,7 @@ const Cart = () => {
<td data-th="Product">
<div className="row">
<div className="col-md-3 text-left">
<img src="https://dummyimage.com/250x250/ced4da/6c757d.jpg" alt="" className="img-fluid d-none d-md-block rounded mb-2 shadow" />
<img src={`${process.env.REACT_APP_API}/Image/250x250/ced4da/6c757d`} alt="" className="img-fluid d-none d-md-block rounded mb-2 shadow" />
</div>
<div className="col-md-9 text-left mt-sm-2">
<h4>{item.title}</h4>

View File

@ -22,7 +22,11 @@ type KnownAction = RequestAction | ReceiveAction
export const actionCreators = {
requestBlogCatalog: (props?: GetBlogCatalogRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetBlogCatalogResponseModel>>('https://localhost:7151/api/BlogCatalog', props?.pathParams, props?.searchParams)
const locale = getState().content?.localization.locale
const searchParams = {...props?.searchParams, locale}
Get<Promise<GetBlogCatalogResponseModel>>(`${process.env.REACT_APP_API}/Image/${process.env.REACT_APP_BLOGITEMS}/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
.then(response => response)
.then(data => {
if(data)
@ -42,7 +46,7 @@ const unloadedState: BlogCatalogState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -52,7 +56,7 @@ const unloadedState: BlogCatalogState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -66,7 +70,7 @@ const unloadedState: BlogCatalogState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -76,7 +80,7 @@ const unloadedState: BlogCatalogState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -90,7 +94,7 @@ const unloadedState: BlogCatalogState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -100,7 +104,7 @@ const unloadedState: BlogCatalogState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -114,7 +118,7 @@ const unloadedState: BlogCatalogState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -124,7 +128,7 @@ const unloadedState: BlogCatalogState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},

View File

@ -22,7 +22,11 @@ type KnownAction = RequestAction | ReceiveAction
export const actionCreators = {
requestBlogCategories: (props?: GetBlogCategoriesRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetBlogCategoriesResponseModel>>('https://localhost:7151/api/BlogCategories', props?.pathParams, props?.searchParams)
const locale = getState().content?.localization.locale
const searchParams = {...props?.searchParams, locale}
Get<Promise<GetBlogCategoriesResponseModel>>(`${process.env.REACT_APP_API}/Image/${process.env.REACT_APP_CATEGORYITEMS}/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
.then(response => response)
.then(data => {
if(data)

View File

@ -24,9 +24,9 @@ export const actionCreators = {
const locale = getState().content?.localization.locale
const searchParams = {...props?.pathParams, locale}
const searchParams = {...props?.searchParams, locale}
Get<Promise<GetBlogFeaturedResponseModel>>(`https://localhost:7151/api/BlogItems/Featured/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
Get<Promise<GetBlogFeaturedResponseModel>>(`${process.env.REACT_APP_API}/Image/${process.env.REACT_APP_BLOGITEMS_FEAUTERED}/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
.then(response => response)
.then(data => {
if(data)
@ -44,7 +44,7 @@ const unloadedState: BlogFeaturedState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -53,7 +53,7 @@ const unloadedState: BlogFeaturedState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -68,7 +68,7 @@ const unloadedState: BlogFeaturedState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -77,7 +77,7 @@ const unloadedState: BlogFeaturedState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -92,7 +92,7 @@ const unloadedState: BlogFeaturedState = {
slug: "demo-post",
badges: [ "demo" ],
image: {
src: "https://dummyimage.com/850x350/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/850x350/dee2e6/6c757d`,
alt: "..."
},
title: "Lorem ipsum",
@ -101,7 +101,7 @@ const unloadedState: BlogFeaturedState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},

View File

@ -22,7 +22,11 @@ type KnownAction = RequestAction | ReceiveAction
export const actionCreators = {
requestBlogItem: (props?: GetBlogItemRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetBlogItemResponseModel>>('https://localhost:7151/api/BlogItem', props?.pathParams, props?.searchParams)
const locale = getState().content?.localization.locale
const searchParams = {...props?.searchParams, locale}
Get<Promise<GetBlogItemResponseModel>>(`${process.env.REACT_APP_API}/Image/${process.env.REACT_APP_BLOGITEM}/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
.then(response => response)
.then(data => {
if(data)
@ -37,7 +41,7 @@ const unloadedState: BlogItemState = {
id: "",
slug: "demo-post",
image: {
src: "https://dummyimage.com/900x400/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/900x400/ced4da/6c757d`,
alt: "..."
},
badges: [
@ -56,7 +60,7 @@ const unloadedState: BlogItemState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -68,7 +72,7 @@ const unloadedState: BlogItemState = {
id: "",
nickName: "Commenter Name 1",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},
@ -80,7 +84,7 @@ const unloadedState: BlogItemState = {
id: "",
nickName: "Commenter Name 4",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},
@ -91,7 +95,7 @@ const unloadedState: BlogItemState = {
id: "",
nickName: "Commenter Name 3",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},
@ -104,7 +108,7 @@ const unloadedState: BlogItemState = {
id: "",
nickName: "Commenter Name 2",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},

View File

@ -23,7 +23,7 @@ type KnownAction = RequestAction | ReceiveAction;
export const actionCreators = {
requestContent: (props?: GetContentRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetContentResponseModel>>(`https://localhost:7151/api/Content/${process.env.REACT_APP_SITEID}`, props?.pathParams, props?.searchParams)
Get<Promise<GetContentResponseModel>>(`${process.env.REACT_APP_API}/Image/${process.env.REACT_APP_CONTENT}/${process.env.REACT_APP_SITEID}`, props?.pathParams, props?.searchParams)
.then(response => response)
.then((data) => {
if(data) {
@ -142,7 +142,7 @@ const unloadedState: ContentState = {
text: "The <code>ClientApp</code> subdirectory is a standard React application based on the <code>create-react-app</code> template. If you open a command prompt in that directory, you can run <code>yarn</code> commands such as <code>yarn test</code> or <code>yarn install</code>.",
reviewer: {
id: "",
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
fullName: "Admin",
position: "CEO, MAKS-IT"
}

View File

@ -79,7 +79,7 @@ const unloadedState: ShopCartState = {
{
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
title: "Shop item title",
brandName: "Brand & Name",
shortText: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...",
@ -91,7 +91,7 @@ const unloadedState: ShopCartState = {
{
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
title: "Shop item title",
brandName: "Brand & Name",
shortText: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...",
@ -103,7 +103,7 @@ const unloadedState: ShopCartState = {
{
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
title: "Shop item title",
brandName: "Brand & Name",
shortText: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eaque fugit ratione dicta mollitia. Officiis ad...",

View File

@ -22,7 +22,11 @@ type KnownAction = RequestAction | ReceiveAction
export const actionCreators = {
requestShopCatalog: (props?: GetShopCatalogRequestModel): AppThunkAction<KnownAction> => (dispatch, getState) => {
Get<Promise<GetShopCatalogResponseModel>>('https://localhost:7151/api/ShopCatalog', props?.pathParams, props?.searchParams)
const locale = getState().content?.localization.locale
const searchParams = { ...props?.searchParams, locale }
Get<Promise<GetShopCatalogResponseModel>>(`${process.env.REACT_APP_API}/Image/${process.env.REACT_APP_SHOPITEMS}/${process.env.REACT_APP_SITEID}`, props?.pathParams, searchParams)
.then(response => response)
.then(data => {
if(data)
@ -41,7 +45,7 @@ const unloadedState: ShopCatalogState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -50,7 +54,7 @@ const unloadedState: ShopCatalogState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),
@ -65,7 +69,7 @@ const unloadedState: ShopCatalogState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -74,7 +78,7 @@ const unloadedState: ShopCatalogState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),
@ -89,7 +93,7 @@ const unloadedState: ShopCatalogState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale", "out of stock" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -98,7 +102,7 @@ const unloadedState: ShopCatalogState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),
@ -113,7 +117,7 @@ const unloadedState: ShopCatalogState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -122,7 +126,7 @@ const unloadedState: ShopCatalogState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),

View File

@ -39,7 +39,7 @@ const unloadedState: ShopFeaturedState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -48,7 +48,7 @@ const unloadedState: ShopFeaturedState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),

View File

@ -38,7 +38,7 @@ const unloadedState: ShopItemState = {
id: "",
slug: "demo-post",
image: {
src: "https://dummyimage.com/600x700/dee2e6/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/600x700/dee2e6/6c757d`,
alt: "..."
},
@ -56,7 +56,7 @@ const unloadedState: ShopItemState = {
id: "",
nickName: "Admin",
image: {
src: "https://dummyimage.com/40x40/ced4da/6c757d",
src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`,
alt: "..."
}
},
@ -74,7 +74,7 @@ const unloadedState: ShopItemState = {
id: "",
nickName: "Commenter Name 1",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},
@ -86,7 +86,7 @@ const unloadedState: ShopItemState = {
id: "",
nickName: "Commenter Name 4",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},
@ -97,7 +97,7 @@ const unloadedState: ShopItemState = {
id: "",
nickName: "Commenter Name 3",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},
@ -110,7 +110,7 @@ const unloadedState: ShopItemState = {
id: "",
nickName: "Commenter Name 2",
image: {
src: "https://dummyimage.com/50x50/ced4da/6c757d.jpg",
src: `${process.env.REACT_APP_API}/Image/50x50/ced4da/6c757d`,
alt: "..."
}
},

View File

@ -39,7 +39,7 @@ const unloadedState: ShopRelatedState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale", "best offer" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -48,7 +48,7 @@ const unloadedState: ShopRelatedState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),
@ -63,7 +63,7 @@ const unloadedState: ShopRelatedState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale", "best offer" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -72,7 +72,7 @@ const unloadedState: ShopRelatedState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),
@ -87,7 +87,7 @@ const unloadedState: ShopRelatedState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale", "best offer" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -96,7 +96,7 @@ const unloadedState: ShopRelatedState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),
@ -111,7 +111,7 @@ const unloadedState: ShopRelatedState = {
id: '',
slug: "shop-catalog-item",
sku: "SKU-0",
image: { src: "https://dummyimage.com/450x300/dee2e6/6c757d.jpg", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/450x300/dee2e6/6c757d`, alt: "..." },
badges: [ "sale", "best offer" ],
title: "Shop item title",
brandName: "Brand & Name",
@ -120,7 +120,7 @@ const unloadedState: ShopRelatedState = {
text: "",
author: {
id: '',
image: { src: "https://dummyimage.com/40x40/ced4da/6c757d", alt: "..." },
image: { src: `${process.env.REACT_APP_API}/Image/40x40/ced4da/6c757d`, alt: "..." },
nickName: "Admin"
},
created: (new Date).toString(),

View File

@ -15,6 +15,7 @@ namespace DataProviders.Collections
(ShopDocument?, IDomainResult) GetBySlug(Guid siteId, string slug);
(List<ShopDocument>?, IDomainResult) GetBySlugs(Guid siteId, List<string> slugs);
(List<ShopDocument>?, IDomainResult) GetAll(Guid siteId, int skip, int take);
(int?, IDomainResult) Count(Guid siteId);
(Guid?, IDomainResult) Update(ShopDocument shopCart);
IDomainResult Delete(Guid id);
IDomainResult DeleteAll(Guid siteId);
@ -56,6 +57,11 @@ namespace DataProviders.Collections
public (List<ShopDocument>?, IDomainResult) GetAll(Guid siteId, int skip, int take) =>
GetWithPredicate(x => x.SiteId == siteId, x => x, skip, take);
public (int?, IDomainResult) Count(Guid siteId) {
var (list, result) = GetWithPredicate(x => x.SiteId == siteId, x => x.Id);
return (list?.Count, result);
}
public (Guid?, IDomainResult) Update(ShopDocument shopCart) =>
UpdateWithPredicate(shopCart, x => x.Id == shopCart.Id);

View File

@ -15,53 +15,51 @@ namespace ImageProvider.Extensions {
}
}
internal static IImageProcessingContext ApplyScalingWaterMarkSimple(this IImageProcessingContext processingContext,
Font font,
string text,
Color color,
float padding) {
private static IImageProcessingContext ApplyScalingWaterMarkSimple(this IImageProcessingContext processingContext,
Font font,
string text,
Color color,
float padding) {
Size imgSize = processingContext.GetCurrentSize();
float targetWidth = imgSize.Width - (padding * 2);
float targetHeight = imgSize.Height - (padding * 2);
// measure the text size
FontRectangle size = TextMeasurer.Measure(text, new RendererOptions(font));
// Measure the text size
FontRectangle size = TextMeasurer.Measure(text, new TextOptions(font));
//find out how much we need to scale the text to fill the space (up or down)
float scalingFactor = Math.Min(imgSize.Width / size.Width, imgSize.Height / size.Height);
// Find out how much we need to scale the text to fill the space (up or down)
float scalingFactor = Math.Min(targetWidth / size.Width, targetHeight / size.Height);
//create a new font
// Create a new font
Font scaledFont = new Font(font, scalingFactor * font.Size);
var center = new PointF(imgSize.Width / 2, imgSize.Height / 2);
var textGraphicOptions = new TextGraphicsOptions() {
TextOptions = {
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
}
var textOptions = new TextOptions(scaledFont) {
Origin = center,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
return processingContext.DrawText(textGraphicOptions, text, scaledFont, color, center);
return processingContext.DrawText(textOptions, text, color);
}
internal static IImageProcessingContext ApplyScalingWaterMarkWordWrap(this IImageProcessingContext processingContext,
Font font,
string text,
Color color,
float padding) {
private static IImageProcessingContext ApplyScalingWaterMarkWordWrap(this IImageProcessingContext processingContext,
Font font,
string text,
Color color,
float padding) {
Size imgSize = processingContext.GetCurrentSize();
float targetWidth = imgSize.Width - (padding * 2);
float targetHeight = imgSize.Height - (padding * 2);
float targetMinHeight = imgSize.Height - (padding * 3); // must be with in a margin width of the target height
float targetMinHeight = imgSize.Height - (padding * 3); // Must be with in a margin width of the target height
// now we are working i 2 dimensions at once and can't just scale because it will cause the text to
// Now we are working in 2 dimensions at once and can't just scale because it will cause the text to
// reflow we need to just try multiple times
var scaledFont = font;
FontRectangle s = new FontRectangle(0, 0, float.MaxValue, float.MaxValue);
float scaleFactor = (scaledFont.Size / 2); // every time we change direction we half this size
float scaleFactor = (scaledFont.Size / 2); // Every time we change direction we half this size
int trapCount = (int)scaledFont.Size * 2;
if (trapCount < 10) {
trapCount = 10;
@ -72,7 +70,7 @@ namespace ImageProvider.Extensions {
while ((s.Height > targetHeight || s.Height < targetMinHeight) && trapCount > 0) {
if (s.Height > targetHeight) {
if (isTooSmall) {
scaleFactor = scaleFactor / 2;
scaleFactor /= 2;
}
scaledFont = new Font(scaledFont, scaledFont.Size - scaleFactor);
@ -81,27 +79,26 @@ namespace ImageProvider.Extensions {
if (s.Height < targetMinHeight) {
if (!isTooSmall) {
scaleFactor = scaleFactor / 2;
scaleFactor /= 2;
}
scaledFont = new Font(scaledFont, scaledFont.Size + scaleFactor);
isTooSmall = true;
}
trapCount--;
s = TextMeasurer.Measure(text, new RendererOptions(scaledFont) {
WrappingWidth = targetWidth
s = TextMeasurer.Measure(text, new TextOptions(scaledFont) {
WrappingLength = targetWidth
});
}
var center = new PointF(padding, imgSize.Height / 2);
var textGraphicOptions = new TextGraphicsOptions() {
TextOptions = {
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
WrapTextWidth = targetWidth
}
var textOptions = new TextOptions(scaledFont) {
Origin = center,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
WrappingLength = targetWidth
};
return processingContext.DrawText(textGraphicOptions, text, scaledFont, color, center);
return processingContext.DrawText(textOptions, text, color);
}
}
}

View File

@ -9,7 +9,7 @@ namespace ImageProvider.Extensions {
var fontCollection = new FontCollection();
foreach (var font in Directory.EnumerateFiles(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Fonts"), "*.ttf", SearchOption.AllDirectories))
fontCollection.Install(font);
fontCollection.Add(font);
return fontCollection;
});

View File

@ -2,12 +2,17 @@
using ImageProvider.Fonts;
using Microsoft.Extensions.Logging;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Drawing;
using static System.Net.Mime.MediaTypeNames;
using ImageProvider.Extensions;
namespace ImageProvider {
public interface IImageProvider {
(byte[]?, IDomainResult) Resize(byte[] bytes, int width, int height);
(byte[]?, IDomainResult) ResizeAndWatermark(byte[] bytes, int width, int height, FontsEnum fontName, FontStylesEnum fontStyle, string text);
(byte[]?, IDomainResult) CreatePlaceholder(int width, int height, string background, string foreground);
}
public class ImageProvider : IImageProvider {
@ -60,5 +65,34 @@ namespace ImageProvider {
return IDomainResult.Failed<byte[]?>();
}
}
public (byte[]?, IDomainResult) CreatePlaceholder(int width, int height, string backgroundHex, string foregroundHex) {
var font = _fontCollection.Families.Single(x => x.Name == FontsEnum.Montserrat.Name)
.CreateFont(10, FontStyle.Regular);
using var image = new Image<Rgba32>(width, height);
if (!Color.TryParseHex(backgroundHex, out Color backgroundColor))
backgroundColor = Color.Gray;
if (!Color.TryParseHex(foregroundHex, out Color foregroundColor))
foregroundColor = Color.White;
image.Mutate(ctx => {
ctx.BackgroundColor(backgroundColor);
ctx.ApplyScalingWaterMark(font, $"{width}x{height}", foregroundColor, 5, false);
//x.Fill(, new Rectangle(0, 0, width, height));
//x.DrawText($"{width}x{height}", font, Color.Black, new PointF(10, 10));
});
using var stream = new MemoryStream();
image.SaveAsJpeg(stream);
return IDomainResult.Success(stream.ToArray());
}
}
}

View File

@ -10,9 +10,9 @@
<PackageReference Include="DomainResult.Common" Version="3.1.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta0013" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.0" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta19" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.0.1" />
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta15" />
</ItemGroup>
<ItemGroup>

View File

@ -9,7 +9,6 @@ using DomainResults.Common;
using WeatherForecast.Policies;
using DomainObjects.Documents.Users;
using WeatherForecast.Controllers.Abstractions;
using static System.Net.WebRequestMethods;
namespace WeatherForecast.Controllers;
@ -146,6 +145,33 @@ public class ImageController : AuthorizationControllerBase {
FileDownloadName = file.Name
};
}
/// <summary>
/// Site wide
/// <para>
/// Allowed everyone
/// </para>
/// </summary>
/// <param name="siteId"></param>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="background"></param>
/// <param name="foreground"></param>
/// <returns></returns>
[HttpGet("{width}x{height}/{background}/{foreground}")]
public IActionResult Get([FromRoute] int width, [FromRoute] int height, [FromRoute] string background, [FromRoute] string foreground) {
var (file, result) = _imageService.Get(width, height, background, foreground);
if (!result.IsSuccess || file == null)
return result.ToActionResult();
var stream = new MemoryStream(file.Bytes);
return new FileStreamResult(stream, file.ContentType) {
FileDownloadName = file.Name
};
}
#endregion
#region Update

View File

@ -32,10 +32,10 @@ namespace WeatherForecast.Models.Cetegories.Requests {
/// <returns></returns>
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (CurrentPage > 0)
if (CurrentPage < 1)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(CurrentPage)}");
if (ItemsPerPage > 0)
if (ItemsPerPage < 1)
yield return new ValidationResult($"{Errors.WrongOrNotManaged} {nameof(ItemsPerPage)}");
if (Locale == Locales.Unknown)

View File

@ -11,6 +11,8 @@ using Core.Abstractions;
using WeatherForecast.Models.Images.Responses;
using Microsoft.AspNetCore.Mvc;
using DomainObjects.Documents.Users;
using Org.BouncyCastle.Bcpg.OpenPgp;
using DomainObjects.Documents.Sites;
namespace WeatherForecast.Services {
@ -42,6 +44,16 @@ namespace WeatherForecast.Services {
/// <returns></returns>
(GetImageResponseModel?, IDomainResult) Get([FromRoute] Guid siteId, [FromRoute] Guid? userId, [FromRoute] Guid fileId);
/// <summary>
///
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="background"></param>
/// <param name="foreground"></param>
/// <returns></returns>
(GetImageResponseModel?, IDomainResult) Get(int width, int height, string background, string foreground);
/// <summary>
///
/// </summary>
@ -174,6 +186,26 @@ namespace WeatherForecast.Services {
}
/// <summary>
///
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="background"></param>
/// <param name="foreground"></param>
/// <returns></returns>
public (GetImageResponseModel?, IDomainResult) Get(int width, int height, string background, string foreground) {
var (file, downloadResult) = _imageProvider.CreatePlaceholder(width, height, background, foreground);
if (!downloadResult.IsSuccess || file == null)
return (null, downloadResult);
return IDomainResult.Success(new GetImageResponseModel() {
Name = "Dummy.jpg",
Bytes = file,
ContentType = "image/jpeg"
});
}
/// <summary>
///
/// </summary>

View File

@ -7,6 +7,7 @@ using DomainObjects.Documents;
using DomainObjects.Enumerations;
using WeatherForecast.Models.ShopCart.Requests;
using WeatherForecast.Models.ShopCart.Responses;
using DomainObjects.Documents.Sites;
namespace WeatherForecast.Services
{
@ -55,7 +56,16 @@ namespace WeatherForecast.Services
/// <param name="requestData"></param>
/// <returns></returns>
public (List<GetShopCartItemLocalizedResponseModel>?, IDomainResult) Get(List<ShopCartDocument> cartItems, GetShopCartItemsLocalizedRequestModel requestData) {
//var (count, getCountResult) = _shopCatalogDataProvider.Count(siteId);
//if (!getCountResult.IsSuccess || count == null)
// return (null, getCountResult);
//var skip = (requestData.CurrentPage - 1) * requestData.ItemsPerPage;
//var take = requestData.ItemsPerPage;
//var totalPages = (int)Math.Ceiling((decimal)count / take);
var items = new List<GetShopCartItemLocalizedResponseModel>();
foreach (var cartItem in cartItems) {
var (item, result) = _shopCatalogDataProvider.Get(cartItem.Id, cartItem.Sku);

View File

@ -65,27 +65,35 @@ namespace WeatherForecast.Services {
/// <returns></returns>
public (GetShopItemsLocalizedResponseModel?, IDomainResult) Get(Guid siteId, GetShopItemsLocalizedRequestModel requestData) {
try {
var (items, result) = _shopCatalogDataProvider.GetAll(siteId, (requestData.CurrentPage - 1) * requestData.ItemsPerPage, requestData.ItemsPerPage);
var (count, getCountResult) = _shopCatalogDataProvider.Count(siteId);
if (!getCountResult.IsSuccess || count == null)
return (null, getCountResult);
if (!result.IsSuccess || items == null)
return (null, result);
var skip = (requestData.CurrentPage - 1) * requestData.ItemsPerPage;
var take = requestData.ItemsPerPage;
var shopItems = new List<GetShopItemLocalizedResponseModel>();
foreach (var item in items) {
var totalPages = (int)Math.Ceiling((decimal)count / take);
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, item.Categories);
var (shopItems, getShopItemsResult) = _shopCatalogDataProvider.GetAll(siteId, skip, take);
if (!getShopItemsResult.IsSuccess || shopItems == null)
return (null, getShopItemsResult);
var result = new List<GetShopItemLocalizedResponseModel>();
foreach (var shopItem in shopItems) {
var (categories, getCategoryResult) = _categoryDataProvider.GetMany(siteId, shopItem.Categories);
if (!getCategoryResult.IsSuccess || categories == null)
return IDomainResult.Failed<GetShopItemsLocalizedResponseModel?>();
var (author, getAuthor) = _userDataProvider.Get(item.Author);
var (author, getAuthor) = _userDataProvider.Get(shopItem.Author);
if (!getAuthor.IsSuccess || author == null)
return IDomainResult.Failed<GetShopItemsLocalizedResponseModel?>();
shopItems.Add(new GetShopItemLocalizedResponseModel(item, categories, author, requestData.Locale));
result.Add(new GetShopItemLocalizedResponseModel(shopItem, categories, author, requestData.Locale));
}
return shopItems.Count > 0
? IDomainResult.Success(new GetShopItemsLocalizedResponseModel(requestData.CurrentPage, 0, shopItems))
return result.Count > 0
? IDomainResult.Success(new GetShopItemsLocalizedResponseModel(requestData.CurrentPage, totalPages, result))
: IDomainResult.NotFound<GetShopItemsLocalizedResponseModel?>();
}
catch (Exception ex) {

View File

@ -24,11 +24,11 @@
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.4" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.18.1" />
<PackageReference Include="Serilog.Enrichers.Span" Version="3.1.0" />
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Expressions" Version="3.4.1" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="5.0.1" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.1.0" />
<PackageReference Include="Serilog.Settings.Configuration" Version="3.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

View File

@ -31,6 +31,14 @@ services:
networks:
- "my-network"
#clientapp:
# environment:
# - ASPNETCORE_ENVIRONMENT=Development
# ports:
# - "3000:3000"
# networks:
# - "my-network"
mongo:
image: mongo
restart: always

View File

@ -11,4 +11,9 @@ services:
build:
context: .
dockerfile: ReverseProxy/Dockerfile
#clientapp:
# image: ${DOCKER_REGISTRY-}clientapp
# build:
# context: .
# dockerfile: ClientApp/Dockerfile

View File

@ -3,4 +3,4 @@ WiredTiger 10.0.2: (December 21, 2021)
WiredTiger version
major=10,minor=0,patch=2
file:WiredTiger.wt
access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.123211=(addr="018081e4f52354c18181e493d377368281e4a22aa0f5808080e301ffc0e3010fc0",order=123211,time=1679862041,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=154,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=370276,run_write_gen=370143)),checkpoint_backup_info=,checkpoint_lsn=(70,62976)
access_pattern_hint=none,allocation_size=4KB,app_metadata=,assert=(commit_timestamp=none,durable_timestamp=none,read_timestamp=none,write_timestamp=off),block_allocation=best,block_compressor=,cache_resident=false,checksum=on,collator=,columns=,dictionary=0,encryption=(keyid=,name=),format=btree,huffman_key=,huffman_value=,id=0,ignore_in_memory_cache_size=false,internal_item_max=0,internal_key_max=0,internal_key_truncate=true,internal_page_max=4KB,key_format=S,key_gap=10,leaf_item_max=0,leaf_key_max=0,leaf_page_max=32KB,leaf_value_max=0,log=(enabled=true),memory_page_image_max=0,memory_page_max=5MB,os_cache_dirty_max=0,os_cache_max=0,prefix_compression=false,prefix_compression_min=4,readonly=false,split_deepen_min_child=0,split_deepen_per_child=0,split_pct=90,tiered_object=false,tiered_storage=(auth_token=,bucket=,bucket_prefix=,cache_directory=,local_retention=300,name=,object_target_size=0),value_format=S,verbose=[],version=(major=1,minor=1),write_timestamp_usage=none,checkpoint=(WiredTigerCheckpoint.124102=(addr="018381e487d81b1f8481e4bf0e4b478581e4ba5850aa808080e301ffc0e3010fc0",order=124102,time=1680030284,size=81920,newest_start_durable_ts=0,oldest_start_ts=0,newest_txn=29,newest_stop_durable_ts=0,newest_stop_ts=-1,newest_stop_txn=-11,prepare=0,write_gen=372999,run_write_gen=372970)),checkpoint_backup_info=,checkpoint_lsn=(73,16000)

View File

@ -4,7 +4,11 @@
"commandName": "DockerCompose",
"commandVersion": "1.0",
"serviceActions": {
"weatherforecast": "StartDebugging"
"mongo": "StartWithoutDebugging",
"mongo-express": "StartWithoutDebugging",
"reverseproxy": "StartWithoutDebugging",
"weatherforecast": "StartDebugging",
// "clientapp": "StartDebugging"
}
}
}