diff --git a/api/resolvers/item.js b/api/resolvers/item.js
index d712c634..9baa35df 100644
--- a/api/resolvers/item.js
+++ b/api/resolvers/item.js
@@ -78,7 +78,7 @@ export default {
let items; let user; let pins; let subFull
const subClause = (num) => {
- return sub ? ` AND "subName" = $${num} ` : ` AND ("subName" IS NULL OR "subName" = $${3}) `
+ return sub ? ` AND "subName" = $${num} ` : ` AND ("subName" IS NULL OR "subName" = $${num}) `
}
const activeOrMine = () => {
@@ -165,9 +165,10 @@ export default {
${timedLeftJoinWeightedSats(1)}
WHERE "parentId" IS NULL AND created_at <= $1 AND created_at > $3
AND "pinId" IS NULL
+ ${subClause(4)}
${timedOrderBySats(1)}
OFFSET $2
- LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, new Date(new Date() - 7))
+ LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, new Date(new Date() - 7), sub || 'NULL')
}
if (decodedCursor.offset !== 0 || items?.length < LIMIT) {
@@ -177,9 +178,10 @@ export default {
${timedLeftJoinWeightedSats(1)}
WHERE "parentId" IS NULL AND created_at <= $1
AND "pinId" IS NULL
+ ${subClause(3)}
${timedOrderBySats(1)}
OFFSET $2
- LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset)
+ LIMIT ${LIMIT}`, decodedCursor.time, decodedCursor.offset, sub || 'NULL')
}
if (decodedCursor.offset === 0) {
@@ -532,8 +534,9 @@ export default {
const checkSats = async () => {
// check if the user has the funds to run for the first minute
- const minuteMsats = maxBid / 1296
- const user = models.user.findUnique({ where: { id: me.id } })
+ const minuteMsats = maxBid * 5 / 216
+ const user = await models.user.findUnique({ where: { id: me.id } })
+ console.log(user, user.msats, minuteMsats)
if (user.msats < minuteMsats) {
throw new UserInputError('insufficient funds')
}
diff --git a/api/resolvers/notifications.js b/api/resolvers/notifications.js
index 1d7ae3e5..8651cd20 100644
--- a/api/resolvers/notifications.js
+++ b/api/resolvers/notifications.js
@@ -104,6 +104,14 @@ export default {
WHERE "Invite"."userId" = $1
AND users.created_at <= $2
GROUP BY "Invite".id)
+ UNION ALL
+ (SELECT "Item".id::text, "Item"."statusUpdatedAt" AS "sortTime", NULL as "earnedSats",
+ 'JobChanged' AS type
+ FROM "Item"
+ WHERE "Item"."userId" = $1
+ AND "maxBid" IS NOT NULL
+ AND status <> 'STOPPED'
+ AND "statusUpdatedAt" <= $2)
ORDER BY "sortTime" DESC
OFFSET $3
LIMIT ${LIMIT}`, me.id, decodedCursor.time, decodedCursor.offset)
@@ -129,6 +137,9 @@ export default {
Reply: {
item: async (n, args, { models }) => getItem(n, { id: n.id }, { models })
},
+ JobChanged: {
+ item: async (n, args, { models }) => getItem(n, { id: n.id }, { models })
+ },
Mention: {
mention: async (n, args, { models }) => true,
item: async (n, args, { models }) => getItem(n, { id: n.id }, { models })
diff --git a/api/resolvers/user.js b/api/resolvers/user.js
index 6251ac2c..d5384035 100644
--- a/api/resolvers/user.js
+++ b/api/resolvers/user.js
@@ -210,6 +210,23 @@ export default {
return true
}
+ const job = await models.item.findFirst({
+ where: {
+ status: {
+ not: 'STOPPED'
+ },
+ maxBid: {
+ not: null
+ },
+ statusUpdatedAt: {
+ gt: user.checkedNotesAt
+ }
+ }
+ })
+ if (job) {
+ return true
+ }
+
// check if new invites have been redeemed
const newInvitees = await models.$queryRaw(`
SELECT "Invite".id
diff --git a/api/typeDefs/notifications.js b/api/typeDefs/notifications.js
index 704ec4fb..3899418f 100644
--- a/api/typeDefs/notifications.js
+++ b/api/typeDefs/notifications.js
@@ -27,7 +27,12 @@ export default gql`
sortTime: String!
}
- union Notification = Reply | Votification | Mention | Invitification
+ type JobChanged {
+ item: Item!
+ sortTime: String!
+ }
+
+ union Notification = Reply | Votification | Mention | Invitification | JobChanged
type Notifications {
lastChecked: String
diff --git a/components/job-form.js b/components/job-form.js
index 15fb6d9c..ac8b9b4e 100644
--- a/components/job-form.js
+++ b/components/job-form.js
@@ -92,7 +92,7 @@ export default function JobForm ({ item, sub }) {
- You only pay as many sats/mo as required to maintain your position relative to other
- posts and only up to your max bid.
+ posts (or {sub.baseCost} sats/mo) and only up to your max bid.
- Your sats/mo must be a multiple of 1000 sats
@@ -147,7 +147,7 @@ export default function JobForm ({ item, sub }) {
if (item) {
router.push(`/items/${item.id}`)
} else {
- router.push(`/$${sub.name}/recent`)
+ router.push(`/~${sub.name}/recent`)
}
})}
>
@@ -198,21 +198,24 @@ export default function JobForm ({ item, sub }) {
function StatusControl ({ item }) {
let StatusComp
- if (item.status === 'ACTIVE') {
+ if (item.status !== 'STOPPED') {
StatusComp = () => {
return (
-
I want to stop my job }
- headerColor='var(--danger)'
- body={
- stop my job} name='stop' inline
- />
+ <>
+
+ I want to stop my job}
+ headerColor='var(--danger)'
+ body={
+ stop my job} name='stop' inline
+ />
}
- />
+ />
+ >
)
}
- } else if (item.status === 'STOPPED') {
+ } else {
StatusComp = () => {
return (
)
}
- } else {
- StatusComp = () => {
- return (
-
- )
- }
}
return (
+ {item.status === 'NOSATS' &&
+
}
)
diff --git a/components/notifications.js b/components/notifications.js
index 357ccf10..da364624 100644
--- a/components/notifications.js
+++ b/components/notifications.js
@@ -1,6 +1,6 @@
import { useQuery } from '@apollo/client'
import Comment, { CommentSkeleton } from './comment'
-import Item from './item'
+import Item, { ItemJob } from './item'
import { NOTIFICATIONS } from '../fragments/notifications'
import { useRouter } from 'next/router'
import MoreFooter from './more-footer'
@@ -58,13 +58,21 @@ function Notification ({ n }) {
you were mentioned in
}
-
- {n.item.title
- ?
- : (
-
-
-
)}
+ {n.__typename === 'JobChanged' &&
+
+ {n.item.status === 'NOSATS'
+ ? 'your job ran out of sats'
+ : 'your job is active again'}
+ }
+
+ {n.item.maxBid
+ ?
+ : n.item.title
+ ?
+ : (
+
+
+
)}
>)}
diff --git a/fragments/notifications.js b/fragments/notifications.js
index 08d4cf38..f2fbb755 100644
--- a/fragments/notifications.js
+++ b/fragments/notifications.js
@@ -41,6 +41,12 @@ export const NOTIFICATIONS = gql`
...InviteFields
}
}
+ ... on JobChanged {
+ sortTime
+ item {
+ ...ItemFields
+ }
+ }
}
}
} `
diff --git a/prisma/migrations/20220224205443_run_auction/migration.sql b/prisma/migrations/20220224205443_run_auction/migration.sql
index 7202db38..241397bc 100644
--- a/prisma/migrations/20220224205443_run_auction/migration.sql
+++ b/prisma/migrations/20220224205443_run_auction/migration.sql
@@ -1,3 +1,5 @@
+ALTER TABLE "Item" RENAME COLUMN "noSatsAt" TO "statusUpdatedAt";
+
-- charge the user for the auction item
CREATE OR REPLACE FUNCTION run_auction(item_id INTEGER) RETURNS void AS $$
DECLARE
@@ -9,21 +11,21 @@ CREATE OR REPLACE FUNCTION run_auction(item_id INTEGER) RETURNS void AS $$
PERFORM ASSERT_SERIALIZED();
-- extract data we need
- SELECT ("maxBid" * 1000 / 30 / 24 / 60), "userId", status INTO bid, user_id, item_status FROM "Item" WHERE id = item_id;
+ SELECT ("maxBid" * 5 / 216), "userId", status INTO bid, user_id, item_status FROM "Item" WHERE id = item_id;
SELECT msats INTO user_msats FROM users WHERE id = user_id;
-- check if user wallet has enough sats
IF bid > user_msats THEN
- -- if not, set status = NOSATS and noSatsAt to now_utc if not already set
+ -- if not, set status = NOSATS and statusUpdatedAt to now_utc if not already set
IF item_status <> 'NOSATS' THEN
- UPDATE "Item" SET status = 'NOSATS', "noSatsAt" = now_utc() WHERE id = item_id;
+ UPDATE "Item" SET status = 'NOSATS', "statusUpdatedAt" = now_utc() WHERE id = item_id;
END IF;
ELSE
-- if so, deduct from user
UPDATE users SET msats = msats - bid WHERE id = user_id;
- -- update item status = ACTIVE and noSatsAt = null if NOSATS
+ -- update item status = ACTIVE and statusUpdatedAt = null if NOSATS
IF item_status = 'NOSATS' THEN
- UPDATE "Item" SET status = 'ACTIVE', "noSatsAt" = null WHERE id = item_id;
+ UPDATE "Item" SET status = 'ACTIVE', "statusUpdatedAt" = now_utc() WHERE id = item_id;
END IF;
END IF;
END;
diff --git a/prisma/migrations/20220226164520_status_update/migration.sql b/prisma/migrations/20220226164520_status_update/migration.sql
deleted file mode 100644
index 55caefc5..00000000
--- a/prisma/migrations/20220226164520_status_update/migration.sql
+++ /dev/null
@@ -1,33 +0,0 @@
--- AlterTable
-ALTER TABLE "Item" RENAME COLUMN "noSatsAt" TO "statusUpdatedAt";
-
--- charge the user for the auction item
-CREATE OR REPLACE FUNCTION run_auction(item_id INTEGER) RETURNS void AS $$
- DECLARE
- bid INTEGER;
- user_id INTEGER;
- user_msats INTEGER;
- item_status "Status";
- BEGIN
- PERFORM ASSERT_SERIALIZED();
-
- -- extract data we need
- SELECT ("maxBid" * 1000 / 30 / 24 / 60), "userId", status INTO bid, user_id, item_status FROM "Item" WHERE id = item_id;
- SELECT msats INTO user_msats FROM users WHERE id = user_id;
-
- -- check if user wallet has enough sats
- IF bid > user_msats THEN
- -- if not, set status = NOSATS and statusUpdatedAt to now_utc if not already set
- IF item_status <> 'NOSATS' THEN
- UPDATE "Item" SET status = 'NOSATS', "statusUpdatedAt" = now_utc() WHERE id = item_id;
- END IF;
- ELSE
- -- if so, deduct from user
- UPDATE users SET msats = msats - bid WHERE id = user_id;
- -- update item status = ACTIVE and statusUpdatedAt = null if NOSATS
- IF item_status = 'NOSATS' THEN
- UPDATE "Item" SET status = 'ACTIVE', "statusUpdatedAt" = now_utc() WHERE id = item_id;
- END IF;
- END IF;
- END;
-$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/prisma/migrations/20220226170533_msats_bigint/migration.sql b/prisma/migrations/20220226170533_msats_bigint/migration.sql
deleted file mode 100644
index 0644a838..00000000
--- a/prisma/migrations/20220226170533_msats_bigint/migration.sql
+++ /dev/null
@@ -1,3 +0,0 @@
--- AlterTable
-ALTER TABLE "users" ALTER COLUMN "msats" SET DEFAULT 0,
-ALTER COLUMN "msats" SET DATA TYPE BIGINT;
diff --git a/prisma/migrations/20220226174624_int/migration.sql b/prisma/migrations/20220226174624_int/migration.sql
deleted file mode 100644
index f5bdad1f..00000000
--- a/prisma/migrations/20220226174624_int/migration.sql
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- Warnings:
-
- - You are about to alter the column `msats` on the `users` table. The data in that column could be lost. The data in that column will be cast from `BigInt` to `Integer`.
-
-*/
--- AlterTable
-ALTER TABLE "users" ALTER COLUMN "msats" SET DEFAULT 0,
-ALTER COLUMN "msats" SET DATA TYPE INTEGER;
-
-
--- charge the user for the auction item
-CREATE OR REPLACE FUNCTION run_auction(item_id INTEGER) RETURNS void AS $$
- DECLARE
- bid INTEGER;
- user_id INTEGER;
- user_msats INTEGER;
- item_status "Status";
- BEGIN
- PERFORM ASSERT_SERIALIZED();
-
- -- extract data we need
- SELECT ("maxBid" * 5 / 216), "userId", status INTO bid, user_id, item_status FROM "Item" WHERE id = item_id;
- SELECT msats INTO user_msats FROM users WHERE id = user_id;
-
- -- check if user wallet has enough sats
- IF bid > user_msats THEN
- -- if not, set status = NOSATS and statusUpdatedAt to now_utc if not already set
- IF item_status <> 'NOSATS' THEN
- UPDATE "Item" SET status = 'NOSATS', "statusUpdatedAt" = now_utc() WHERE id = item_id;
- END IF;
- ELSE
- -- if so, deduct from user
- UPDATE users SET msats = msats - bid WHERE id = user_id;
- -- update item status = ACTIVE and statusUpdatedAt = null if NOSATS
- IF item_status = 'NOSATS' THEN
- UPDATE "Item" SET status = 'ACTIVE', "statusUpdatedAt" = now_utc() WHERE id = item_id;
- END IF;
- END IF;
- END;
-$$ LANGUAGE plpgsql;
\ No newline at end of file