wants list redux and removal
This commit is contained in:
1 parent
70a67b0c53
commit
12c3da9f5e
8 files changed
+86
-18
No files matched your search
+1
-1
@@ -28,7 +28,7 @@ async function start() {
|
|||||||
events,
|
events,
|
||||||
} = createServices(log);
|
} = createServices(log);
|
||||||
|
|
||||||
events.emit(Events.StartupSync);
|
// events.emit(Events.StartupSync);
|
||||||
|
|
||||||
api.listen();
|
api.listen();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -177,6 +177,8 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
|
|||||||
ws.on('close', function onClose() {
|
ws.on('close', function onClose() {
|
||||||
log.info('ws disconnected', { user: ctx.state.user });
|
log.info('ws disconnected', { user: ctx.state.user });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await rpc.onConnection();
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
+30
-1
@@ -23,7 +23,6 @@ export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, off
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function offerStatusSet(params: OfferStatusSetParams): Promise<OffersMessage> {
|
async function offerStatusSet(params: OfferStatusSetParams): Promise<OffersMessage> {
|
||||||
log.info(params);
|
|
||||||
const { id, status } = params;
|
const { id, status } = params;
|
||||||
assert(id, 'no id supplied');
|
assert(id, 'no id supplied');
|
||||||
assert(Status[status], 'unknown status');
|
assert(Status[status], 'unknown status');
|
||||||
@@ -32,6 +31,16 @@ export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, off
|
|||||||
return [RpcMessageType.Offers, []]
|
return [RpcMessageType.Offers, []]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function wantRm(params: WantRmParams): Promise<WantsMessage> {
|
||||||
|
const { id } = params;
|
||||||
|
assert(id, 'no id supplied');
|
||||||
|
|
||||||
|
await pg.wantRm(id);
|
||||||
|
|
||||||
|
const wants = await pg.userWants(user);
|
||||||
|
return [RpcMessageType.Wants, wants];
|
||||||
|
}
|
||||||
|
|
||||||
async function receive(message: any): Promise<RpcMessage> {
|
async function receive(message: any): Promise<RpcMessage> {
|
||||||
const [msgType, params] = message;
|
const [msgType, params] = message;
|
||||||
|
|
||||||
@@ -44,6 +53,8 @@ export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, off
|
|||||||
return ping();
|
return ping();
|
||||||
case RpcMessageType.OfferStatusSet:
|
case RpcMessageType.OfferStatusSet:
|
||||||
return offerStatusSet(params);
|
return offerStatusSet(params);
|
||||||
|
case RpcMessageType.WantRm:
|
||||||
|
return wantRm(params);
|
||||||
default:
|
default:
|
||||||
throw new Error(`Message type ${msgType} is known but unhandled`);
|
throw new Error(`Message type ${msgType} is known but unhandled`);
|
||||||
}
|
}
|
||||||
@@ -54,6 +65,12 @@ export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, off
|
|||||||
throw new Error(`Invalid parameters for message type ${msgType}: ${JSON.stringify(message)}`);
|
throw new Error(`Invalid parameters for message type ${msgType}: ${JSON.stringify(message)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function onConnection() {
|
||||||
|
const wants = await pg.userWants(user);
|
||||||
|
const wantsMsg: WantsMessage = [RpcMessageType.Wants, wants];
|
||||||
|
send(wantsMsg);
|
||||||
|
}
|
||||||
|
|
||||||
function send(msg: RpcMessage) {
|
function send(msg: RpcMessage) {
|
||||||
ws.send(JSON.stringify(msg, (key, value) =>
|
ws.send(JSON.stringify(msg, (key, value) =>
|
||||||
typeof value === 'bigint'
|
typeof value === 'bigint'
|
||||||
@@ -65,6 +82,7 @@ export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, off
|
|||||||
return {
|
return {
|
||||||
receive,
|
receive,
|
||||||
send,
|
send,
|
||||||
|
onConnection,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,17 +96,24 @@ export enum RpcMessageType {
|
|||||||
Error = 'Error',
|
Error = 'Error',
|
||||||
|
|
||||||
OfferStatusSet = 'OfferStatusSet',
|
OfferStatusSet = 'OfferStatusSet',
|
||||||
|
|
||||||
|
Wants = 'Wants',
|
||||||
|
WantRm = 'WantRm',
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrorMessage = [RpcMessageType.Error, string];
|
type ErrorMessage = [RpcMessageType.Error, string];
|
||||||
type PongMessage = [RpcMessageType.Pong, []];
|
type PongMessage = [RpcMessageType.Pong, []];
|
||||||
type PingMessage = [RpcMessageType.Ping, []];
|
type PingMessage = [RpcMessageType.Ping, []];
|
||||||
|
type WantsMessage = [RpcMessageType.Wants, Want[]];
|
||||||
type OffersMessage = [RpcMessageType.Offers, Offer[]];
|
type OffersMessage = [RpcMessageType.Offers, Offer[]];
|
||||||
type OfferStatusSetMessage = [RpcMessageType.OfferStatusSet, Offer[]];
|
type OfferStatusSetMessage = [RpcMessageType.OfferStatusSet, Offer[]];
|
||||||
|
|
||||||
export type RpcMessage =
|
export type RpcMessage =
|
||||||
PingMessage |
|
PingMessage |
|
||||||
PongMessage |
|
PongMessage |
|
||||||
|
|
||||||
|
WantsMessage |
|
||||||
|
|
||||||
OffersMessage |
|
OffersMessage |
|
||||||
OfferStatusSetMessage |
|
OfferStatusSetMessage |
|
||||||
ErrorMessage;
|
ErrorMessage;
|
||||||
@@ -98,3 +123,7 @@ type OfferStatusSetParams = {
|
|||||||
id: UUID,
|
id: UUID,
|
||||||
status: Status,
|
status: Status,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type WantRmParams = {
|
||||||
|
id: UUID,
|
||||||
|
};
|
||||||
@@ -1,9 +1,27 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
|
import { useState, useCallback } from 'preact/hooks';
|
||||||
|
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { State } from './../store'
|
||||||
|
|
||||||
|
import http from './../http';
|
||||||
|
|
||||||
function Want(want) {
|
function Want(want) {
|
||||||
console.log(want);
|
|
||||||
const r = want.data;
|
const r = want.data;
|
||||||
|
|
||||||
|
const ws = useSelector((state: State) => state.ws);
|
||||||
|
const [confirm, setConfirm] = useState(false);
|
||||||
|
|
||||||
|
function onClick() {
|
||||||
|
if (confirm) return ws.sendWantRm(want.id);
|
||||||
|
setTimeout(() => setConfirm(false), 2500);
|
||||||
|
return setConfirm(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const text = confirm
|
||||||
|
? 'confirm'
|
||||||
|
: 'remove';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<article key={r.id}>
|
<article key={r.id}>
|
||||||
<div>
|
<div>
|
||||||
@@ -12,6 +30,7 @@ function Want(want) {
|
|||||||
<h5 class='alt-text'>{r.formats[0].descriptions.join(' ')}</h5>
|
<h5 class='alt-text'>{r.formats[0].descriptions.join(' ')}</h5>
|
||||||
</div>
|
</div>
|
||||||
<img src={r.thumb} />
|
<img src={r.thumb} />
|
||||||
|
<button onClick={onClick} >{text}</button>
|
||||||
</article>
|
</article>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import { h } from 'preact';
|
import { h } from 'preact';
|
||||||
import { useState, useEffect } from 'preact/hooks';
|
import { useState, useEffect } from 'preact/hooks';
|
||||||
|
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { State } from './../store'
|
||||||
|
|
||||||
// import style from './style.less';
|
// import style from './style.less';
|
||||||
import http from './../http';
|
import http from './../http';
|
||||||
import Want from './../components/want';
|
import Want from './../components/want';
|
||||||
@@ -12,17 +15,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const List = ({ user }: Props) => {
|
const List = ({ user }: Props) => {
|
||||||
const [wants, setOffers] = useState([]);
|
const wants = useSelector((state: State) => state.wants);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function getWants() {
|
|
||||||
const [error, wants] = await http.getWants();
|
|
||||||
if (error) return console.error(error);
|
|
||||||
setOffers(wants);
|
|
||||||
}
|
|
||||||
getWants();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
|
|
||||||
if (!wants.length) {
|
if (!wants.length) {
|
||||||
return <div> loading... </div>;
|
return <div> loading... </div>;
|
||||||
|
|||||||
+10
-1
@@ -17,6 +17,14 @@ export const offersState = createSlice({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const wantsState = createSlice({
|
||||||
|
name: 'wants',
|
||||||
|
initialState: [],
|
||||||
|
reducers: {
|
||||||
|
set: (state, action) => action.payload
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const wsState = createSlice({
|
export const wsState = createSlice({
|
||||||
name: 'ws',
|
name: 'ws',
|
||||||
initialState: null,
|
initialState: null,
|
||||||
@@ -26,9 +34,10 @@ export const wsState = createSlice({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const reducer = combineReducers({
|
const reducer = combineReducers({
|
||||||
user: userState.reducer,
|
|
||||||
offers: offersState.reducer,
|
offers: offersState.reducer,
|
||||||
|
wants: wantsState.reducer,
|
||||||
ws: wsState.reducer,
|
ws: wsState.reducer,
|
||||||
|
user: userState.reducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
const store = createStore(
|
const store = createStore(
|
||||||
|
|||||||
@@ -232,6 +232,15 @@ article {
|
|||||||
1fr 1fr 1fr 1fr;
|
1fr 1fr 1fr 1fr;
|
||||||
|
|
||||||
article {
|
article {
|
||||||
|
display: grid;
|
||||||
|
grid-template-areas:
|
||||||
|
"title img"
|
||||||
|
"remove remove";
|
||||||
|
|
||||||
|
button {
|
||||||
|
grid-area: remove
|
||||||
|
}
|
||||||
|
|
||||||
padding: var(--base-spacing);
|
padding: var(--base-spacing);
|
||||||
margin: var(--base-spacing-half);
|
margin: var(--base-spacing-half);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-3
@@ -1,5 +1,7 @@
|
|||||||
const SOCKET_URL = `${window.location.protocol === 'https:' ? 'wss://' : 'ws://'}${window.location.host}/api/ws`;
|
const SOCKET_URL = `${window.location.protocol === 'https:' ? 'wss://' : 'ws://'}${window.location.host}/api/ws`;
|
||||||
|
|
||||||
|
import { wantsState, wsState } from './store'
|
||||||
|
|
||||||
export default function createSocket(store) {
|
export default function createSocket(store) {
|
||||||
let ws;
|
let ws;
|
||||||
|
|
||||||
@@ -28,6 +30,10 @@ export default function createSocket(store) {
|
|||||||
send(['OfferStatusSet', { id, status }]);
|
send(['OfferStatusSet', { id, status }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendWantRm(id) {
|
||||||
|
send(['WantRm', { id }]);
|
||||||
|
}
|
||||||
|
|
||||||
let pongTimeout;
|
let pongTimeout;
|
||||||
function onPong() {
|
function onPong() {
|
||||||
pongTimeout = setTimeout(sendPing, 5000);
|
pongTimeout = setTimeout(sendPing, 5000);
|
||||||
@@ -36,8 +42,8 @@ export default function createSocket(store) {
|
|||||||
// -------------
|
// -------------
|
||||||
// Incoming
|
// Incoming
|
||||||
// -------------
|
// -------------
|
||||||
function onSourcesAvailable(clouds) {
|
function onWants(wants) {
|
||||||
// store.dispatch(http.LIBRARY_RECEIVE_POINTCLOUDS, clouds);
|
store.dispatch(wantsState.actions.set(wants));
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------
|
// -------------
|
||||||
@@ -46,7 +52,7 @@ export default function createSocket(store) {
|
|||||||
// when the server sends a reply it will have one of these message types
|
// when the server sends a reply it will have one of these message types
|
||||||
// this object wraps the reply types to a function
|
// this object wraps the reply types to a function
|
||||||
const handlers = {
|
const handlers = {
|
||||||
SourcesAvailable: onSourcesAvailable,
|
Wants: onWants,
|
||||||
|
|
||||||
Pong: onPong,
|
Pong: onPong,
|
||||||
Error: errHandler,
|
Error: errHandler,
|
||||||
@@ -109,5 +115,6 @@ export default function createSocket(store) {
|
|||||||
connect,
|
connect,
|
||||||
|
|
||||||
sendOfferStatusSet,
|
sendOfferStatusSet,
|
||||||
|
sendWantRm,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user