diff --git a/dnas/herd/zomes/coordinator/posts/src/comment.rs b/dnas/herd/zomes/coordinator/posts/src/comment.rs index 7a288ba..e85d90b 100644 --- a/dnas/herd/zomes/coordinator/posts/src/comment.rs +++ b/dnas/herd/zomes/coordinator/posts/src/comment.rs @@ -178,6 +178,29 @@ pub fn downvote_comment(original_post_hash: ActionHash) -> ExternResult<()> { Ok(()) } +#[hdk_extern] +pub fn rmvote_comment(comment_hash: ActionHash) -> ExternResult<()> { + get_links( + agent_info()?.agent_initial_pubkey.clone(), + LinkTypes::MyVotedComments, + None, + )?.iter().for_each(|link| { + if link.target.clone().to_hex() == comment_hash.to_hex() { + let _ = delete_link(link.create_link_hash.clone()); + } + }); + get_links( + comment_hash, + LinkTypes::CommentVoteByAgent, + None, + )?.iter().for_each(|link| { + if link.target.clone().to_hex() == agent_info().unwrap().agent_initial_pubkey.to_hex() { + let _ = delete_link(link.create_link_hash.clone()); + } + }); + Ok(()) +} + #[hdk_extern] pub fn get_my_vote_on_comment(comment_hash: ActionHash) -> ExternResult> { // Get all votes on this comment diff --git a/dnas/herd/zomes/coordinator/posts/src/post.rs b/dnas/herd/zomes/coordinator/posts/src/post.rs index 1aafe23..ce51463 100644 --- a/dnas/herd/zomes/coordinator/posts/src/post.rs +++ b/dnas/herd/zomes/coordinator/posts/src/post.rs @@ -133,6 +133,17 @@ pub fn upvote_post(original_post_hash: ActionHash) -> ExternResult<()> { Ok(()) } +#[hdk_extern] +pub fn rmvote_post(original_post_hash: ActionHash) -> ExternResult<()> { + create_link( + original_post_hash, + agent_info()?.agent_initial_pubkey, + LinkTypes::PostVoteByAgent, + make_vote_link_tag(0)?, + )?; + Ok(()) +} + #[hdk_extern] pub fn downvote_post(original_post_hash: ActionHash) -> ExternResult<()> { create_link( diff --git a/dnas/herd/zomes/integrity/posts/src/votes.rs b/dnas/herd/zomes/integrity/posts/src/votes.rs index 33ad4a9..db80939 100644 --- a/dnas/herd/zomes/integrity/posts/src/votes.rs +++ b/dnas/herd/zomes/integrity/posts/src/votes.rs @@ -60,7 +60,7 @@ pub fn validate_create_link_vote_by_agent( // TODO: make this a DNA property // Value must be -1 or 1 - if vote_tag.value != -1 && vote_tag.value != 1 { + if vote_tag.value > 1 || vote_tag.value < -1 { return Ok( ValidateCallbackResult::Invalid( String::from("VotePostToAgent tag value must be 1 or -1"), diff --git a/flake.lock b/flake.lock index 039c2f3..9662fc9 100644 --- a/flake.lock +++ b/flake.lock @@ -156,16 +156,16 @@ "holochain": { "flake": false, "locked": { - "lastModified": 1675455504, - "narHash": "sha256-619bpPtO0IUSzPzLNzHERuvqGblpjO65rsw3jdxoEkQ=", + "lastModified": 1681507583, + "narHash": "sha256-lRnums2gv1oXVwo4gMF2QAnzEu8prwxg1uKjUzNwJV4=", "owner": "holochain", "repo": "holochain", - "rev": "ed5b7bb461c2a8bfd4d2633bad604a20b8f2da03", + "rev": "ac50baed6b53e9d0552729e69e1e20312e4edc08", "type": "github" }, "original": { "owner": "holochain", - "ref": "holochain-0.1.3", + "ref": "holochain-0.1.4", "repo": "holochain", "type": "github" } @@ -400,11 +400,11 @@ }, "locked": { "dir": "versions/0_1", - "lastModified": 1679811419, - "narHash": "sha256-Dpz28/2wNsacIw8B4YpV1pKvyy0DT6fSkCRfAbPfKUo=", + "lastModified": 1685773320, + "narHash": "sha256-Yw6wWMzR+cbCmrQBaA+O5qRS3Is5EK+YqBTFRbLo8xI=", "owner": "holochain", "repo": "holochain", - "rev": "c7957817622b1714b6e592c4b38a52216cd21280", + "rev": "c46c6bf2b9db1a2a14d7ca3350cf05f32d210e98", "type": "github" }, "original": { diff --git a/tests/src/posts/posts/post.test.ts b/tests/src/posts/posts/post.test.ts index 2743513..b982033 100644 --- a/tests/src/posts/posts/post.test.ts +++ b/tests/src/posts/posts/post.test.ts @@ -334,6 +334,8 @@ test('get_all_posts_sorted_by_votes sorts by number of votes desc, then timestam }); await pause(2000); + + // All agents see the same post ordering const alice_posts_sorted = await alice.namedCells.get('herd').callZome({ @@ -359,6 +361,23 @@ test('get_all_posts_sorted_by_votes sorts by number of votes desc, then timestam fn_name: "get_all_posts_sorted_by_votes", }); t.deepEqual(john_posts_sorted, [record.signed_action.hashed.hash, record3.signed_action.hashed.hash, record2.signed_action.hashed.hash]) + + // Bob removes his vote to alice's post + await bob.namedCells.get('herd').callZome({ + zome_name: "posts", + fn_name: "rmvote_post", + payload: record.signed_action.hashed.hash, + }); + + await pause(2000); + + const metadata: Record = await alice.namedCells.get('herd').callZome({ + zome_name: "posts", + fn_name: "get_post_metadata", + payload: record.signed_action.hashed.hash, + }); + + t.deepEqual(3, (decode((metadata.entry as any).Present.entry) as any).upvotes); }, true, diff --git a/ui/src/components/BaseVoteInput.vue b/ui/src/components/BaseVoteInput.vue index 542ca73..62df587 100644 --- a/ui/src/components/BaseVoteInput.vue +++ b/ui/src/components/BaseVoteInput.vue @@ -3,7 +3,7 @@
import { defineEmits } from 'vue' -defineEmits(['upvote', 'downvote']); +defineEmits(['upvote', 'downvote', 'rmvote']); withDefaults(defineProps<{ votes?: number, diff --git a/ui/src/herd/posts/CommentVotes.vue b/ui/src/herd/posts/CommentVotes.vue index 1214067..bb26b47 100644 --- a/ui/src/herd/posts/CommentVotes.vue +++ b/ui/src/herd/posts/CommentVotes.vue @@ -4,6 +4,7 @@ :my-vote="myVote" @upvote="upvote" @downvote="downvote" + @rmvote="rmvote" /> @@ -20,7 +21,7 @@ const props = defineProps<{ votes?: number }>(); -const emit = defineEmits(['upvote', 'downvote']); +const emit = defineEmits(['upvote', 'downvote', 'rmvote']); const client = (inject('client') as ComputedRef).value; @@ -73,6 +74,24 @@ const downvote = async () => { } }; +const rmvote = async () => { + if(myVote.value === 0) return; + + try { + await client.callZome({ + cell_id: [props.dnaHash, client.myPubKey], + zome_name: 'posts', + fn_name: 'rmvote_comment', + payload: props.originalActionHash, + }); + emit('rmvote'); + runFetchMyVote(); + } catch (e: any) { + toast.error("Failed to vote on post: ", e.data.data); + console.log(e); + } +}; + const {data: myVote, run: runFetchMyVote } = useRequest(fetchMyVote, { onError: (e: any) => { toast.error(`Failed to fetch post votes count: ${e.data.data}`); diff --git a/ui/src/herd/posts/PostVotes.vue b/ui/src/herd/posts/PostVotes.vue index 812f8f0..5b83d3b 100644 --- a/ui/src/herd/posts/PostVotes.vue +++ b/ui/src/herd/posts/PostVotes.vue @@ -6,6 +6,7 @@ :my-vote="myVote" @upvote="upvote" @downvote="downvote" + @rmvote="rmvote" /> @@ -26,7 +27,7 @@ const props = withDefaults(defineProps<{ size: 'lg' }); -const emit = defineEmits(['upvote', 'downvote']); +const emit = defineEmits(['upvote', 'downvote', 'rmvote']); const client = (inject('client') as ComputedRef).value; const getMyVote = async () => { @@ -64,6 +65,24 @@ const upvote = async() => { } }; +const rmvote = async () => { + if(myVote.value === 0) return; + + try { + await client.callZome({ + cell_id: [props.dnaHash, client.myPubKey], + cap_secret: null, + zome_name: 'posts', + fn_name: 'rmvote_post', + payload: props.postHash, + }); + emit('rmvote'); + runGetMyVote(); + } catch (e: any) { + toast.error(`Failed to rmvote post: ${e.data.data}`); + } +}; + const downvote = async () => { if(myVote.value === -1) return;