adding listing management and easy content adds

This commit is contained in:
Hunter Miller 2022-07-17 20:46:36 -05:00
parent 5c2e31a6f1
commit 55e85fe48d
10 changed files with 85 additions and 15 deletions

View File

@ -100,14 +100,20 @@
?+ mark ~|(bad-poke/mark !!) ?+ mark ~|(bad-poke/mark !!)
%declare %declare
=+ !<(=declare:s vase) =+ !<(=declare:s vase)
di-abet:(publish declare di-core) (publish declare cor)
::
%declarations
=+ !<(decs=(list declare:s) vase)
=. cor (roll decs publish)
cor
::
%remove %remove
=+ !<(=hash:s vase) =+ !<(=hash:s vase)
di-abet:di-remove:(di-abed:di-core hash) di-abet:di-remove:(di-abed:di-core hash)
== ==
++ publish ++ publish
|= [=declare:s core=_di-core] |= [=declare:s core=_cor]
^+ di-core ^+ cor
:: ::
?> from-self ?> from-self
=/ listing =/ listing
@ -119,8 +125,8 @@
== ==
?: (~(has by directory) hash.listing) ?: (~(has by directory) hash.listing)
~& 'Listing already exists.' ~& 'Listing already exists.'
di-core cor
(di-publish:(di-abed:core hash.listing) listing) di-abet:(di-publish:(di-abed:di-core:core hash.listing) listing)
-- --
:: ::
++ watch ++ watch
@ -169,6 +175,9 @@
|= =path |= =path
^- (unit (unit cage)) ^- (unit (unit cage))
?+ path [~ ~] ?+ path [~ ~]
[%x %published ~]
``directory+!>(published)
::
[%x %lookup @ @ @ @ ~] [%x %lookup @ @ @ @ ~]
=- ``search+!>(-) =- ``search+!>(-)
^- search:s ^- search:s

View File

@ -30,6 +30,12 @@
size/n/(scot %ud size.search) size/n/(scot %ud size.search)
total/n/(scot %ud total.search) total/n/(scot %ud total.search)
== ==
++ directory
|= d=directory:s
%- pairs
%+ turn ~(tap by d)
|= [=hash:s l=listing:s]
[(scot %uv hash) (listing l)]
-- --
++ dejs ++ dejs
=, dejs:format =, dejs:format

View File

@ -5,6 +5,7 @@
++ grow ++ grow
|% |%
++ noun directory ++ noun directory
++ json (directory:enjs:j directory)
-- --
++ grab ++ grab
|% |%

View File

@ -27,7 +27,7 @@ export const Listings = ({ listings, remove, className }: ListingsProps) => {
} }
return ( return (
<ul className={cn('px-2 space-y-6', className)}> <ul className={cn('space-y-6', className)}>
{listings && listings.map(l => ( {listings && listings.map(l => (
<li key={l.hash}> <li key={l.hash}>
<article className='group-1 flex w-full'> <article className='group-1 flex w-full'>

View File

@ -31,7 +31,7 @@ export const Meta = ({ className }: MetaProps) => {
{version && <span className='mb-[3px]'>v{version}</span>} {version && <span className='mb-[3px]'>v{version}</span>}
</div> </div>
<a <a
className="inline-block font-mono default-ring underline rounded-md hover:text-rosy mb-4" className="inline-block font-mono default-ring underline rounded-md hover:text-rosy"
href="web+urbitgraph://group/~nocsyx-lassul/sphinx" href="web+urbitgraph://group/~nocsyx-lassul/sphinx"
> >
~nocsyx-lassul/sphinx ~nocsyx-lassul/sphinx

View File

@ -1,9 +1,10 @@
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import api from '../api';
import { PostOptions } from '../components/PostOptions'; import { PostOptions } from '../components/PostOptions';
import { useApps } from '../state/apps'; import { useApps } from '../state/apps';
import { PostOption, PostOptionsForm } from '../types/sphinx'; import { Declare, Listing, PostOption, PostOptionsForm } from '../types/sphinx';
function getAppKeys(apps: PostOption[]): string[] { function getAppKeys(apps: PostOption[]): string[] {
return apps.map(({ key }) => key); return apps.map(({ key }) => key);
@ -27,9 +28,19 @@ export const Apps = () => {
} }
}, [apps, options, setValue]); }, [apps, options, setValue]);
const onSubmit = useCallback(() => { const onSubmit = useCallback((values: PostOptionsForm) => {
debugger;
api.poke<Declare[]>({
app: 'sphinx',
mark: 'declarations',
json: apps.filter(a => values.options.includes(a.key)).map(a => ({
post: a.post,
reach: 'friends'
}))
});
reset(); reset();
}, [reset]); }, [apps, reset]);
return ( return (
<> <>

View File

@ -1,9 +1,10 @@
import React, { useCallback, useEffect, useState } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form'; import { FormProvider, useForm } from 'react-hook-form';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import api from '../api';
import { PostOptions } from '../components/PostOptions'; import { PostOptions } from '../components/PostOptions';
import { useGroups } from '../state/groups'; import { useGroups } from '../state/groups';
import { PostOption, PostOptionsForm } from '../types/sphinx'; import { Declare, PostOption, PostOptionsForm } from '../types/sphinx';
export const Groups = () => { export const Groups = () => {
const groups = useGroups(); const groups = useGroups();
@ -34,7 +35,16 @@ export const Groups = () => {
} }
}, [groups, options, setValue]); }, [groups, options, setValue]);
const onSubmit = useCallback(() => { const onSubmit = useCallback((values: PostOptionsForm) => {
api.poke<Declare[]>({
app: 'sphinx',
mark: 'declarations',
json: groups.filter(a => values.options.includes(a.key)).map(a => ({
post: a.post,
reach: 'friends'
}))
});
reset(); reset();
}, [reset]); }, [reset]);

View File

@ -1,5 +1,34 @@
import { size } from 'lodash';
import React from 'react'; import React from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import api from '../api';
import { Listings } from '../components/Listings';
import { Directory, Remove } from '../types/sphinx';
export const MyListings = () => { export const MyListings = () => {
return <div />; const queryClient = useQueryClient();
const { data } = useQuery('published', () => api.scry<Directory>({
app: 'sphinx',
path: '/published'
}));
const { mutate } = useMutation((hash: string) => {
return api.poke<Remove>({
app: 'sphinx',
mark: 'remove',
json: hash
})
}, {
onSuccess: () => {
queryClient.invalidateQueries('published');
}
});
return (
<>
<header className='flex items-center'>
<h1 className='text-2xl font-semibold'>My Listings</h1>
</header>
<Listings listings={Object.values(data || {})} remove={mutate} className="mt-6" />
</>
)
} }

View File

@ -4,12 +4,12 @@ import api from "../api";
import { Post } from "../types/sphinx"; import { Post } from "../types/sphinx";
function getAppPost(app: string, vat: Vat, charge: Charge): Post { function getAppPost(app: string, vat: Vat, charge: Charge): Post {
const ship = vat.arak.rail?.publisher || vat.arak.rail?.ship; const ship = vat.arak.rail?.publisher || vat.arak.rail?.ship || `~${window.ship}`;
return { return {
type: 'app', type: 'app',
title: charge.title, title: charge.title,
link: `${ship}/${app}`, link: `web+urbitgraph://${ship}/${app}`,
description: charge.info || charge.title, description: charge.info || charge.title,
image: charge.image || '', image: charge.image || '',
tags: ['app'] tags: ['app']

View File

@ -33,6 +33,10 @@ export type Search = {
total: number; total: number;
} }
export interface Directory {
[hash: string]: Listing;
}
export interface PostOption { export interface PostOption {
post: Post; post: Post;
key: string; key: string;