on master help sign in
adding listing management and easy content adds
55e85feHunter Miller
desk/app/sphinx.hoon+14−5
@@ -100,14 +100,20 @@
100 ?+ mark ~|(bad-poke/mark !!)
100 ?+ mark ~|(bad-poke/mark !!)
101 %declare
101 %declare
102 =+ !<(=declare:s vase)
102 =+ !<(=declare:s vase)
103− di-abet:(publish declare di-core)
103+ (publish declare cor)
104+ ::
105+ %declarations
106+ =+ !<(decs=(list declare:s) vase)
107+ =. cor (roll decs publish)
108+ cor
109+ ::
104 %remove
110 %remove
105 =+ !<(=hash:s vase)
111 =+ !<(=hash:s vase)
106 di-abet:di-remove:(di-abed:di-core hash)
112 di-abet:di-remove:(di-abed:di-core hash)
107 ==
113 ==
108 ++ publish
114 ++ publish
109− |= [=declare:s core=_di-core]
115+ |= [=declare:s core=_cor]
110− ^+ di-core
116+ ^+ cor
111 ::
117 ::
112 ?> from-self
118 ?> from-self
113 =/ listing
119 =/ listing
@@ -119,8 +125,8 @@
119 ==
125 ==
120 ?: (~(has by directory) hash.listing)
126 ?: (~(has by directory) hash.listing)
121 ~& 'Listing already exists.'
127 ~& 'Listing already exists.'
122− di-core
128+ cor
123− (di-publish:(di-abed:core hash.listing) listing)
129+ di-abet:(di-publish:(di-abed:di-core:core hash.listing) listing)
124 --
130 --
125::
131::
126++ watch
132++ watch
@@ -169,6 +175,9 @@
169 |= =path
175 |= =path
170 ^- (unit (unit cage))
176 ^- (unit (unit cage))
171 ?+ path [~ ~]
177 ?+ path [~ ~]
178+ [%x %published ~]
179+ ``directory+!>(published)
180+ ::
172 [%x %lookup @ @ @ @ ~]
181 [%x %lookup @ @ @ @ ~]
173 =- ``search+!>(-)
182 =- ``search+!>(-)
174 ^- search:s
183 ^- search:s
desk/lib/sphinx-json.hoon+6
@@ -30,6 +30,12 @@
30 size/n/(scot %ud size.search)
30 size/n/(scot %ud size.search)
31 total/n/(scot %ud total.search)
31 total/n/(scot %ud total.search)
32 ==
32 ==
33+ ++ directory
34+ |= d=directory:s
35+ %- pairs
36+ %+ turn ~(tap by d)
37+ |= [=hash:s l=listing:s]
38+ [(scot %uv hash) (listing l)]
33 --
39 --
34++ dejs
40++ dejs
35 =, dejs:format
41 =, dejs:format
desk/mar/directory.hoon+1
@@ -5,6 +5,7 @@
5++ grow
5++ grow
6 |%
6 |%
7 ++ noun directory
7 ++ noun directory
8+ ++ json (directory:enjs:j directory)
8 --
9 --
9++ grab
10++ grab
10 |%
11 |%
ui/src/components/Listings.tsx+1−1
@@ -27,7 +27,7 @@ export const Listings = ({ listings, remove, className }: ListingsProps) => {
27 }
27 }
28
28
29 return (
29 return (
30− <ul className={cn('px-2 space-y-6', className)}>
30+ <ul className={cn('space-y-6', className)}>
31 {listings && listings.map(l => (
31 {listings && listings.map(l => (
32 <li key={l.hash}>
32 <li key={l.hash}>
33 <article className='group-1 flex w-full'>
33 <article className='group-1 flex w-full'>
ui/src/components/Meta.tsx+1−1
@@ -31,7 +31,7 @@ export const Meta = ({ className }: MetaProps) => {
31 {version && <span className='mb-[3px]'>v{version}</span>}
31 {version && <span className='mb-[3px]'>v{version}</span>}
32 </div>
32 </div>
33 <a
33 <a
34− className="inline-block font-mono default-ring underline rounded-md hover:text-rosy mb-4"
34+ className="inline-block font-mono default-ring underline rounded-md hover:text-rosy"
35 href="web+urbitgraph://group/~nocsyx-lassul/sphinx"
35 href="web+urbitgraph://group/~nocsyx-lassul/sphinx"
36 >
36 >
37 ~nocsyx-lassul/sphinx
37 ~nocsyx-lassul/sphinx
ui/src/manage-listings/Apps.tsx+14−3
@@ -1,9 +1,10 @@
1import React, { useCallback, useEffect, useState } from 'react';
1import React, { useCallback, useEffect, useState } from 'react';
2import { FormProvider, useForm } from 'react-hook-form';
2import { FormProvider, useForm } from 'react-hook-form';
3import { Link } from 'react-router-dom';
3import { Link } from 'react-router-dom';
4+import api from '../api';
4import { PostOptions } from '../components/PostOptions';
5import { PostOptions } from '../components/PostOptions';
5import { useApps } from '../state/apps';
6import { useApps } from '../state/apps';
6−import { PostOption, PostOptionsForm } from '../types/sphinx';
7+import { Declare, Listing, PostOption, PostOptionsForm } from '../types/sphinx';
7
8
8function getAppKeys(apps: PostOption[]): string[] {
9function getAppKeys(apps: PostOption[]): string[] {
9 return apps.map(({ key }) => key);
10 return apps.map(({ key }) => key);
@@ -27,9 +28,19 @@ export const Apps = () => {
27 }
28 }
28 }, [apps, options, setValue]);
29 }, [apps, options, setValue]);
29
30
30− const onSubmit = useCallback(() => {
31+ const onSubmit = useCallback((values: PostOptionsForm) => {
32+ debugger;
33+ api.poke<Declare[]>({
34+ app: 'sphinx',
35+ mark: 'declarations',
36+ json: apps.filter(a => values.options.includes(a.key)).map(a => ({
37+ post: a.post,
38+ reach: 'friends'
39+ }))
40+ });
41+
31 reset();
42 reset();
32− }, [reset]);
43+ }, [apps, reset]);
33
44
34 return (
45 return (
35 <>
46 <>
ui/src/manage-listings/Groups.tsx+12−2
@@ -1,9 +1,10 @@
1import React, { useCallback, useEffect, useState } from 'react';
1import React, { useCallback, useEffect, useState } from 'react';
2import { FormProvider, useForm } from 'react-hook-form';
2import { FormProvider, useForm } from 'react-hook-form';
3import { Link } from 'react-router-dom';
3import { Link } from 'react-router-dom';
4+import api from '../api';
4import { PostOptions } from '../components/PostOptions';
5import { PostOptions } from '../components/PostOptions';
5import { useGroups } from '../state/groups';
6import { useGroups } from '../state/groups';
6−import { PostOption, PostOptionsForm } from '../types/sphinx';
7+import { Declare, PostOption, PostOptionsForm } from '../types/sphinx';
7
8
8export const Groups = () => {
9export const Groups = () => {
9 const groups = useGroups();
10 const groups = useGroups();
@@ -34,7 +35,16 @@ export const Groups = () => {
34 }
35 }
35 }, [groups, options, setValue]);
36 }, [groups, options, setValue]);
36
37
37− const onSubmit = useCallback(() => {
38+ const onSubmit = useCallback((values: PostOptionsForm) => {
39+ api.poke<Declare[]>({
40+ app: 'sphinx',
41+ mark: 'declarations',
42+ json: groups.filter(a => values.options.includes(a.key)).map(a => ({
43+ post: a.post,
44+ reach: 'friends'
45+ }))
46+ });
47+
38 reset();
48 reset();
39 }, [reset]);
49 }, [reset]);
40
50
ui/src/manage-listings/MyListings.tsx+30−1
@@ -1,5 +1,34 @@
1+import { size } from 'lodash';
1import React from 'react';
2import React from 'react';
3+import { useMutation, useQuery, useQueryClient } from 'react-query';
4+import api from '../api';
5+import { Listings } from '../components/Listings';
6+import { Directory, Remove } from '../types/sphinx';
2
7
3export const MyListings = () => {
8export const MyListings = () => {
9+ const queryClient = useQueryClient();
10+ const { data } = useQuery('published', () => api.scry<Directory>({
11+ app: 'sphinx',
12+ path: '/published'
13+ }));
14+ const { mutate } = useMutation((hash: string) => {
15+ return api.poke<Remove>({
16+ app: 'sphinx',
17+ mark: 'remove',
18+ json: hash
19+ })
20+ }, {
21+ onSuccess: () => {
22+ queryClient.invalidateQueries('published');
23+ }
24+ });
25+
4− return <div />;
26+ return (
27+ <>
28+ <header className='flex items-center'>
29+ <h1 className='text-2xl font-semibold'>My Listings</h1>
30+ </header>
31+ <Listings listings={Object.values(data || {})} remove={mutate} className="mt-6" />
32+ </>
33+ )
5}
34}
ui/src/state/apps.ts+2−2
@@ -4,12 +4,12 @@ import api from "../api";
4import { Post } from "../types/sphinx";
4import { Post } from "../types/sphinx";
5
5
6function getAppPost(app: string, vat: Vat, charge: Charge): Post {
6function getAppPost(app: string, vat: Vat, charge: Charge): Post {
7− const ship = vat.arak.rail?.publisher || vat.arak.rail?.ship;
7+ const ship = vat.arak.rail?.publisher || vat.arak.rail?.ship || `~${window.ship}`;
8
8
9 return {
9 return {
10 type: 'app',
10 type: 'app',
11 title: charge.title,
11 title: charge.title,
12− link: `${ship}/${app}`,
12+ link: `web+urbitgraph://${ship}/${app}`,
13 description: charge.info || charge.title,
13 description: charge.info || charge.title,
14 image: charge.image || '',
14 image: charge.image || '',
15 tags: ['app']
15 tags: ['app']
ui/src/types/sphinx.ts+4
@@ -33,6 +33,10 @@ export type Search = {
33 total: number;
33 total: number;
34}
34}
35
35
36+export interface Directory {
37+ [hash: string]: Listing;
38+}
39+
36export interface PostOption {
40export interface PostOption {
37 post: Post;
41 post: Post;
38 key: string;
42 key: string;