Compare commits
3
Commits
toasts
...
sample-offers
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c99b148e15 | ||
|
|
ffc023f419 | ||
|
|
a0cd49b411 |
No files matched your search
Generated
+41
@@ -29,6 +29,7 @@
|
|||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
"@types/bluebird": "^3.5.36",
|
"@types/bluebird": "^3.5.36",
|
||||||
"@types/koa": "^2.13.5",
|
"@types/koa": "^2.13.5",
|
||||||
|
"@types/koa-websocket": "^5.0.7",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/mocha": "^9.1.1",
|
"@types/mocha": "^9.1.1",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
@@ -325,6 +326,17 @@
|
|||||||
"@types/koa": "*"
|
"@types/koa": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/koa-websocket": {
|
||||||
|
"version": "5.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/koa-websocket/-/koa-websocket-5.0.7.tgz",
|
||||||
|
"integrity": "sha512-zv5F0iaV9zk3iXLzvskUZKgX35RW7F7UNX3tK1FNQUn2nierQWlY2aM0dBTYs0kLVLRtBhsxcUdiKzDp9JPOAw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/koa": "*",
|
||||||
|
"@types/koa-compose": "*",
|
||||||
|
"@types/ws": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/lodash": {
|
"node_modules/@types/lodash": {
|
||||||
"version": "4.14.182",
|
"version": "4.14.182",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
|
||||||
@@ -382,6 +394,15 @@
|
|||||||
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
|
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/ws": {
|
||||||
|
"version": "8.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
|
||||||
|
"integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ungap/promise-all-settled": {
|
"node_modules/@ungap/promise-all-settled": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
|
||||||
@@ -3961,6 +3982,17 @@
|
|||||||
"@types/koa": "*"
|
"@types/koa": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/koa-websocket": {
|
||||||
|
"version": "5.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/koa-websocket/-/koa-websocket-5.0.7.tgz",
|
||||||
|
"integrity": "sha512-zv5F0iaV9zk3iXLzvskUZKgX35RW7F7UNX3tK1FNQUn2nierQWlY2aM0dBTYs0kLVLRtBhsxcUdiKzDp9JPOAw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/koa": "*",
|
||||||
|
"@types/koa-compose": "*",
|
||||||
|
"@types/ws": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/lodash": {
|
"@types/lodash": {
|
||||||
"version": "4.14.182",
|
"version": "4.14.182",
|
||||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
|
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz",
|
||||||
@@ -4018,6 +4050,15 @@
|
|||||||
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
|
"integrity": "sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/ws": {
|
||||||
|
"version": "8.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
|
||||||
|
"integrity": "sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@ungap/promise-all-settled": {
|
"@ungap/promise-all-settled": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"@types/bcrypt": "^5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
"@types/bluebird": "^3.5.36",
|
"@types/bluebird": "^3.5.36",
|
||||||
"@types/koa": "^2.13.5",
|
"@types/koa": "^2.13.5",
|
||||||
|
"@types/koa-websocket": "^5.0.7",
|
||||||
"@types/lodash": "^4.14.182",
|
"@types/lodash": "^4.14.182",
|
||||||
"@types/mocha": "^9.1.1",
|
"@types/mocha": "^9.1.1",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
|||||||
+9
-2
@@ -14,11 +14,13 @@ import type Log from 'bunyan';
|
|||||||
import type { Listing, User, Want, Prisma } from '@prisma/client';
|
import type { Listing, User, Want, Prisma } from '@prisma/client';
|
||||||
|
|
||||||
import { Pg } from './pg';
|
import { Pg } from './pg';
|
||||||
|
import { Discogs } from './discogs';
|
||||||
|
import { Offers } from './offers';
|
||||||
import routerAuth from './routers/router.auth';
|
import routerAuth from './routers/router.auth';
|
||||||
import { Events } from './events';
|
import { Events } from './events';
|
||||||
import createRpc, { RpcMessageType } from './rpc';
|
import createRpc, { RpcMessageType } from './rpc';
|
||||||
|
|
||||||
export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
|
export default function createApi(log: Log, pg: Pg, discogs: Discogs, offers: Offers, events) {
|
||||||
const PORT = 41337;
|
const PORT = 41337;
|
||||||
const WS_PORT = 40055;
|
const WS_PORT = 40055;
|
||||||
const SECRET = 'ohja4Eif9eidah3aj5ta2haa4iemooth';
|
const SECRET = 'ohja4Eif9eidah3aj5ta2haa4iemooth';
|
||||||
@@ -110,13 +112,15 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
|
|||||||
|
|
||||||
app.ws.use(passport.initialize());
|
app.ws.use(passport.initialize());
|
||||||
app.ws.use(passport.session());
|
app.ws.use(passport.session());
|
||||||
|
|
||||||
app.ws.use(async (ctx, next) => {
|
app.ws.use(async (ctx, next) => {
|
||||||
|
try {
|
||||||
log.info('new ws connection', { user: ctx.state.user });
|
log.info('new ws connection', { user: ctx.state.user });
|
||||||
|
|
||||||
// log.child...
|
// log.child...
|
||||||
|
|
||||||
const ws = ctx.websocket;
|
const ws = ctx.websocket;
|
||||||
const rpc = createRpc(log, pg, ctx.state.user, ws, discogs, offers);
|
const rpc = createRpc(log, pg, ws, discogs, offers, ctx.state.user);
|
||||||
|
|
||||||
if (ctx.state.user) events.emit(Events.Connection, { ws, id: ctx.state.user.id });
|
if (ctx.state.user) events.emit(Events.Connection, { ws, id: ctx.state.user.id });
|
||||||
ws.on('message', async function incoming(message) {
|
ws.on('message', async function incoming(message) {
|
||||||
@@ -137,6 +141,9 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await rpc.onConnection();
|
await rpc.onConnection();
|
||||||
|
} catch (e) {
|
||||||
|
log.error(e);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -112,3 +112,5 @@ export default function createDiscogs(log: Log, pg: Pg) {
|
|||||||
search,
|
search,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Discogs = ReturnType<typeof createDiscogs>;
|
||||||
@@ -131,11 +131,20 @@ export default function createOffers(log: Log, pg: Pg) {
|
|||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function samples() {
|
||||||
|
const user = await pg.userFindEmail('ntr@mnml.gg');
|
||||||
|
const offerGroups = await userOffers(user);
|
||||||
|
return offerGroups.slice(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
generate,
|
generate,
|
||||||
accept,
|
accept,
|
||||||
statusSet,
|
statusSet,
|
||||||
acpOffers,
|
acpOffers,
|
||||||
userOffers,
|
userOffers,
|
||||||
|
samples,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Offers = ReturnType<typeof createOffers>;
|
||||||
+16
-2
@@ -6,7 +6,10 @@ import type Log from 'bunyan';
|
|||||||
|
|
||||||
import type { Want, Offer, User } from '@prisma/client';
|
import type { Want, Offer, User } from '@prisma/client';
|
||||||
|
|
||||||
import { Pg } from './pg';
|
import type { Pg } from './pg';
|
||||||
|
import type { Discogs } from './discogs';
|
||||||
|
import type { Offers } from './offers';
|
||||||
|
|
||||||
import { Status } from './offers';
|
import { Status } from './offers';
|
||||||
import { isAdmin } from './utils';
|
import { isAdmin } from './utils';
|
||||||
|
|
||||||
@@ -18,7 +21,7 @@ function checkMsgType(msgType: RpcMessageType): msgType is RpcMessageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rpc is created per connection from the api
|
// rpc is created per connection from the api
|
||||||
export default function createRpc(log: Log, pg: Pg, user: User, ws, discogs, offers) {
|
export default function createRpc(log: Log, pg: Pg, ws, discogs: Discogs, offers: Offers, user: User | null) {
|
||||||
async function ping(): Promise<PongMessage> {
|
async function ping(): Promise<PongMessage> {
|
||||||
return [RpcMessageType.Pong, []];
|
return [RpcMessageType.Pong, []];
|
||||||
}
|
}
|
||||||
@@ -109,7 +112,15 @@ 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 anonConnection() {
|
||||||
|
const samples = await offers.samples();
|
||||||
|
const sampleMsg: OfferSamplesMessage = [RpcMessageType.OfferSamples, samples];
|
||||||
|
send(sampleMsg);
|
||||||
|
}
|
||||||
|
|
||||||
async function onConnection() {
|
async function onConnection() {
|
||||||
|
if (!user) return anonConnection();
|
||||||
|
|
||||||
const userMsg: UserMessage = [RpcMessageType.User, user];
|
const userMsg: UserMessage = [RpcMessageType.User, user];
|
||||||
send(userMsg);
|
send(userMsg);
|
||||||
|
|
||||||
@@ -148,6 +159,7 @@ export enum RpcMessageType {
|
|||||||
|
|
||||||
Error = 'Error',
|
Error = 'Error',
|
||||||
|
|
||||||
|
OfferSamples = 'OfferSamples',
|
||||||
OfferStatusSet = 'OfferStatusSet',
|
OfferStatusSet = 'OfferStatusSet',
|
||||||
|
|
||||||
AcpOfferStatusSet = 'AcpOfferStatusSet',
|
AcpOfferStatusSet = 'AcpOfferStatusSet',
|
||||||
@@ -164,6 +176,7 @@ type UserMessage = [RpcMessageType.User, User];
|
|||||||
type WantsMessage = [RpcMessageType.Wants, Want[]];
|
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[]];
|
||||||
|
type OfferSamplesMessage = [RpcMessageType.OfferSamples, Offer[]];
|
||||||
|
|
||||||
type AcpOfferStatusSetMessage = [RpcMessageType.AcpOfferStatusSet, Offer[]];
|
type AcpOfferStatusSetMessage = [RpcMessageType.AcpOfferStatusSet, Offer[]];
|
||||||
type AcpOffersMessage = [RpcMessageType.AcpOffers, Offer[]];
|
type AcpOffersMessage = [RpcMessageType.AcpOffers, Offer[]];
|
||||||
@@ -178,6 +191,7 @@ export type RpcMessage =
|
|||||||
WantsMessage |
|
WantsMessage |
|
||||||
|
|
||||||
OffersMessage |
|
OffersMessage |
|
||||||
|
OfferSamplesMessage |
|
||||||
OfferStatusSetMessage |
|
OfferStatusSetMessage |
|
||||||
|
|
||||||
AcpOfferStatusSetMessage |
|
AcpOfferStatusSetMessage |
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useSelector, useDispatch } from 'react-redux'
|
|||||||
import http from './../http';
|
import http from './../http';
|
||||||
import { State, userState } from './../store';
|
import { State, userState } from './../store';
|
||||||
import Swirl from './../components/swirl';
|
import Swirl from './../components/swirl';
|
||||||
|
import OfferGroup from './../components/offer.group';
|
||||||
|
|
||||||
const Login = ({ mode }) => {
|
const Login = ({ mode }) => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
@@ -94,16 +95,22 @@ const Login = ({ mode }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function LoginPage({ mode }) {
|
function LoginPage({ mode }) {
|
||||||
|
const offers = useSelector((state: State) => state.offers);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="landing">
|
<div class="landing">
|
||||||
<Login mode={mode} />
|
<Login mode={mode} />
|
||||||
|
<div class='offers'>
|
||||||
|
{offers.map(OfferGroup)}
|
||||||
|
<div>
|
||||||
<Swirl />
|
<Swirl />
|
||||||
<div class='words'>
|
<div class='words'>
|
||||||
<p>Mates Crates is a record importing service.</p>
|
|
||||||
<p>We bundle orders together from thousands of online stores to reduce the cost of shipping vinyl.</p>
|
<p>We bundle orders together from thousands of online stores to reduce the cost of shipping vinyl.</p>
|
||||||
<p>Based in Preston.</p>
|
<p>Based in Preston.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const userState = createSlice({
|
|||||||
|
|
||||||
export const offersState = createSlice({
|
export const offersState = createSlice({
|
||||||
name: 'offers',
|
name: 'offers',
|
||||||
initialState: null,
|
initialState: [],
|
||||||
reducers: {
|
reducers: {
|
||||||
set: (state, action) => action.payload
|
set: (state, action) => action.payload
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -217,6 +217,7 @@ button, [type=submit] {
|
|||||||
grid-gap: calc(var(--spacing-double) * 2);
|
grid-gap: calc(var(--spacing-double) * 2);
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
"login swirl"
|
"login swirl"
|
||||||
|
"login sample"
|
||||||
"login words";
|
"login words";
|
||||||
|
|
||||||
.login {
|
.login {
|
||||||
@@ -227,8 +228,8 @@ button, [type=submit] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.swirl {
|
.swirl {
|
||||||
grid-area: swirl;
|
// grid-area: swirl;
|
||||||
height: 15rem;
|
height: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.words {
|
.words {
|
||||||
@@ -344,8 +345,6 @@ article {
|
|||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
margin-bottom: var(--spacing);
|
|
||||||
|
|
||||||
label, input {
|
label, input {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
@@ -365,7 +364,6 @@ form {
|
|||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin-bottom: var(--spacing-half);
|
margin-bottom: var(--spacing-half);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ export default function createSocket(dispatch) {
|
|||||||
Offers: onOffers,
|
Offers: onOffers,
|
||||||
User: onUser,
|
User: onUser,
|
||||||
|
|
||||||
|
OfferSamples: onOffers,
|
||||||
AcpOffers: onAcpOffers,
|
AcpOffers: onAcpOffers,
|
||||||
|
|
||||||
Pong: onPong,
|
Pong: onPong,
|
||||||
|
|||||||
Reference in new issue
Block a user