Skip to content
This repository has been archived by the owner on Mar 24, 2024. It is now read-only.

[Front] Merge PhotoList | MovePhoto onSuccess - [Back] ProductPostMovePhoto #111

Merged
merged 2 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 9 additions & 12 deletions SoarCraft.AwaiShop/AdminHub/Product/Post.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,38 +38,35 @@ public async Task<uint> ProductPostCreate(string name) {
* <remarks>
* @author Aloento
* @since 0.5.0
* @version 0.1.0
* @version 1.0.0
* </remarks>
*/
public async Task<bool> ProductPostMovePhoto(uint photoId, bool up) {
var orders = await this.Db.Photos
var photos = await this.Db.Photos
.Where(x => x.ProductId == this.Db.Photos
.Where(y => y.PhotoId == photoId)
.Select(z => z.ProductId)
.Single())
.OrderBy(x => x.Order)
.ToListAsync();

var index = orders.FindIndex(x => x.PhotoId == photoId);
var current = orders[index].Order;
var index = photos.FindIndex(x => x.PhotoId == photoId);
var current = photos[index].Order;

if (up) {
if (current == 1)
throw new HubException("Photo already at top");

orders[index - 1].Order = current;
orders[index].Order = (byte)(current - 1);
photos[index - 1].Order = current;
photos[index].Order = (byte)(current - 1);
} else {
if (current == orders.Last().Order)
if (current == photos.Last().Order)
throw new HubException("Photo already at bottom");

orders[index + 1].Order = current;
orders[index].Order = (byte)(current + 1);
photos[index + 1].Order = current;
photos[index].Order = (byte)(current + 1);
}

for (byte i = 0; i < orders.Count; i++)
orders[i].Order = (byte)(i + 1);

await this.Db.SaveChangesAsync();
return true;
}
Expand Down
4 changes: 2 additions & 2 deletions SoarCraft.AwaiShop/SoarCraft.AwaiShop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Hosting.Systemd" Version="8.0.0" />
<PackageReference Include="Microsoft.Identity.Web" Version="2.17.0" />
<PackageReference Include="Microsoft.Identity.Web" Version="2.17.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.2" />
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="8.102.1" />
<PackageReference Include="Z.EntityFramework.Plus.EFCore" Version="8.102.1.1" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@azure/msal-browser": "^3.10.0",
"@azure/msal-common": "^14.7.1",
"@azure/msal-react": "^2.0.12",
"@fluentui/react-components": "^9.46.5",
"@fluentui/react-components": "^9.46.6",
"@fluentui/react-hooks": "^8.6.36",
"@fluentui/react-icons": "^2.0.230",
"@griffel/react": "^1.5.20",
Expand Down Expand Up @@ -53,7 +53,7 @@
},
"devDependencies": {
"@types/lodash-es": "^4.17.12",
"@types/react": "^18.2.58",
"@types/react": "^18.2.60",
"@types/react-dom": "^18.2.19",
"@vitejs/plugin-react-swc": "^3.6.0",
"typescript": "^5.3.3",
Expand Down
1,153 changes: 663 additions & 490 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions src/Helpers/useSWR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Options, Service } from "ahooks/lib/useRequest/src/types";
/**
* @author Aloento
* @since 1.3.5
* @version 0.3.0
* @version 0.4.0
*/
export function useSWR<TData, TParams extends any[]>(
key: string,
Expand All @@ -27,15 +27,15 @@ export function useSWR<TData, TParams extends any[]>(
}
);

function refresh() {
clearCache(key);
localStorage.removeItem(key);
return req.refreshAsync();
}

return {
...req,
refresh: () => {
if (options.useMemory)
clearCache(key);
else
localStorage.removeItem(key);

req.refresh();
}
refresh,
refreshAsync: refresh,
};
}
26 changes: 23 additions & 3 deletions src/Pages/Admin/Product/Photo/Action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,22 @@ import { Button } from "@fluentui/react-components";
import { ArrowDownRegular, ArrowUpRegular } from "@fluentui/react-icons";
import { ICompLog } from "~/Helpers/Logger";
import { useErrorToast } from "~/Helpers/useToast";
import { Hub } from "~/ShopNet";
import { AdminHub } from "~/ShopNet/Admin";
import { IPhotoItem } from ".";
import { AdminProductPhotoEdit } from "./Edit";

/**
* @author Aloento
* @since 1.4.0
* @version 0.1.0
* @version 0.2.0
*/
export function AdminProductPhotoAction(props: IPhotoItem & ICompLog) {
const { Id, ParentLog } = props;
const { Id, ProductId, ParentLog } = props;
const { dispatch } = useErrorToast(ParentLog);

const { mutate } = Hub.Product.Get.usePhotoList(ProductId, ParentLog);

const { run } = AdminHub.Product.Post.useMovePhoto({
manual: true,
onError(e, params) {
Expand All @@ -23,7 +26,24 @@ export function AdminProductPhotoAction(props: IPhotoItem & ICompLog) {
Request: params,
Error: e
});
}
},
onSuccess: (_, [__, up]) => mutate(old => {
const list = old![0];

const index = list.findIndex(x => x.PhotoId === Id);
if (index === -1)
return old;

const newIndex = up ? index - 1 : index + 1;
if (newIndex < 0 || newIndex >= list.length)
return old;

const temp = list[index];
list[index] = list[newIndex];
list[newIndex] = temp;

return old;
})
});

return <>
Expand Down
19 changes: 10 additions & 9 deletions src/Pages/Admin/Product/Photo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,15 @@ const columns: TableColumnDefinition<IPhotoItem>[] = [
* @version 1.0.0
*/
export function AdminProductPhoto({ ProdId }: { ProdId: number }) {
const { data: [list] } = Hub.Product.Get.usePhotoList(ProdId, log);
const { data } = Hub.Product.Get.usePhotoList(ProdId, log);
const list = data
? data[0].map(x => ({
Id: x.PhotoId,
Cover: x.ObjectId,
Caption: x.Caption,
ProductId: x.ProductId
}))
: undefined;

const { dispatch, dispatchToast } = useErrorToast(log);

Expand Down Expand Up @@ -137,14 +145,7 @@ export function AdminProductPhoto({ ProdId }: { ProdId: number }) {
</div>

<DelegateDataGrid
Items={
list?.map(x => ({
Id: x.PhotoId,
Cover: x.ObjectId,
Caption: x.Caption,
ProductId: x.ProductId
}))
}
Items={list}
Columns={columns}
/>
</>
Expand Down
3 changes: 2 additions & 1 deletion src/Pages/Product/Carousel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export function ProductCarousel({ Id }: { Id: number; }) {
const style = useStyles();
const [imgs, setImgs] = useState<[string, string?][]>([[img]]);

const { data: [list] } = Hub.Product.Get.usePhotoList(Id, log);
const { data } = Hub.Product.Get.usePhotoList(Id, log);
const list = data ? data[0] : undefined;

useAsyncEffect(async () => {
if (!list) return;
Expand Down
52 changes: 20 additions & 32 deletions src/ShopNet/Product/Get.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { useConst } from "@fluentui/react-hooks";
import { useAsyncEffect } from "ahooks";
import { useState } from "react";
import type { Logger } from "~/Helpers/Logger";
import { useSWR } from "~/Helpers/useSWR";
import { IComboItem } from "~/Pages/Admin/Product/Combo";
import type { IGallery } from "~/Pages/Gallery";
import { ProductData } from "./Data";
Expand Down Expand Up @@ -115,13 +113,16 @@ export abstract class ProductGet extends ProductData {
* @liveSafe
* @deprecated Use {@link usePhotoList} if possible.
*/
public static async PhotoList(prodId: number, pLog: Logger) {
public static async PhotoList(prodId: number, pLog: Logger): Promise<[ProductData.Photo[], string]> {
const log = pLog.With(...this.Log, "PhotoList");
const ids = await this.GetTimeCache<number[]>(prodId, this.photoList, (x) => x, prodId).catch(log.error);
return this.makePhotoList(prodId, ids || [], log);
}

private static async makePhotoList(prodId: number, ids: number[], log: Logger): Promise<[ProductData.Photo[], string]> {
const index = this.Index(prodId, this.photoList);
await this.getLocker(index);
this.reqPool.add(index);

const ids = await this.Invoke<number[]>(this.photoList, prodId)
.finally(() => this.reqPool.delete(index));

let list = [];
let cover = "";

Expand All @@ -140,7 +141,7 @@ export abstract class ProductGet extends ProductData {
list = list.sort((a, b) => a.Order - b.Order);

if (!cover && list.length > 0) {
log.warn(`Product ${prodId} has no cover photo, using first photo instead`);
log.debug(`Product ${prodId} has no cover photo, using first photo instead`);
return [list, list[0].ObjectId];
}

Expand All @@ -150,31 +151,18 @@ export abstract class ProductGet extends ProductData {
/**
* @author Aloento
* @since 1.4.0
* @version 0.1.0
* @version 0.2.0
*/
public static usePhotoList(prodId: number, pLog: Logger) {
const log = useConst(() => pLog.With(...this.Log, "PhotoList"));
const [list, setList] = useState<ProductData.Photo[]>();
const [cover, setCover] = useState<string>();

const req = this.useTimeCache<number[]>(prodId, this.photoList, {
defaultParams: [prodId],
onError: log.error,
});

useAsyncEffect(async () => {
const ids = req.data;
if (!ids)
return;

const [list, cover] = await this.makePhotoList(prodId, ids, log);
setList(list);
setCover(cover);
}, [req.data]);
const req = useSWR(
this.Index(prodId, this.photoList),
(id) => this.PhotoList(id, pLog),
{
defaultParams: [prodId],
onError: pLog.error
}
);

return {
...req,
data: [list, cover] as const
}
return req;
}
}
4 changes: 2 additions & 2 deletions src/ShopNet/SignalR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,14 @@ export abstract class SignalR {
* @since 1.3.5
* @version 0.1.0
*/
private static readonly reqPool = new Set<string>();
protected static readonly reqPool = new Set<string>();

/**
* @author Aloento
* @since 1.3.5
* @version 0.1.0
*/
private static async getLocker(key: string) {
protected static async getLocker(key: string) {
if (this.reqPool.has(key))
return new Promise<void>(res => {
const t = setTimeout(() => this.reqPool.delete(key), 10000);
Expand Down
Loading