Merge pull request #5091 from urbit/lf/md-edit

metadata-store: refactor, add %edit
This commit is contained in:
matildepark 2021-07-15 16:08:16 -04:00 committed by GitHub
commit 2f94466419
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 309 additions and 152 deletions

View File

@ -289,7 +289,7 @@
::
++ md-fact
|= [=mark =vase]
?. ?=(%metadata-update-1 mark) jn-core
?. ?=(%metadata-update-2 mark) jn-core
=+ !<(=update:metadata vase)
?. ?=(%initial-group -.update) jn-core
?. =(group.update rid) jn-core

View File

@ -113,7 +113,7 @@
(group-update !<(update:group-store q.cage.sign))
[cards this]
::
%metadata-update-1
%metadata-update-2
=^ cards state
(metadata-update !<(update:metadata q.cage.sign))
[cards this]

View File

@ -38,7 +38,7 @@
update:metadata
%metadata-update
%metadata-push-hook
1 1
2 2
%.n
==
+$ state-zero
@ -180,7 +180,7 @@
%kick [watch-store^~ state]
::
%fact
?> ?=(%metadata-update-1 p.cage.sign)
?> ?=(%metadata-update-2 p.cage.sign)
=+ !<(=update:metadata q.cage.sign)
?. ?=(%initial-group -.update) `state
`state(previews (~(del by previews) group.update))
@ -325,7 +325,7 @@
%+ turn ~(tap by associations)
|= [=md-resource:metadata =association:metadata]
%+ poke-our:pass:io %metadata-store
:- %metadata-update-1
:- %metadata-update-2
!> ^- update:metadata
[%remove resource md-resource]
::

View File

@ -14,7 +14,7 @@
update:store
%metadata-update
%metadata-pull-hook
1 1
2 2
==
::
+$ agent (push-hook:push-hook config)
@ -94,7 +94,7 @@
^- (quip card (unit vase))
=/ =update:store !<(update:store vas)
:- ~
?. ?=(?(%add %remove) -.update)
?. ?=(?(%add %remove %edit) -.update)
~
=/ role=(unit (unit role-tag))
(role-for-ship:grp group.update src.bowl)

View File

@ -153,19 +153,146 @@
++ on-poke
|= [=mark =vase]
^- (quip card _this)
?> (team:title our.bowl src.bowl)
?> (team:title [our src]:bowl)
|^
=^ cards state
?+ mark (on-poke:def mark vase)
?(%metadata-action %metadata-update-1)
(poke-metadata-update:mc !<(update:store vase))
?(%metadata-action %metadata-update-2)
(poke-metadata-update !<(update:store vase))
::
%import
(poke-import:mc q.vase)
(poke-import q.vase)
::
%noun ~& +.state `state
==
[cards this]
::
++ poke-metadata-update
|= upd=update:store
^- (quip card _state)
|^
?+ -.upd ~|(%bad-poke !!)
%add (handle-add +.upd)
%remove (handle-remove +.upd)
%edit (handle-edit +.upd)
%initial-group (handle-initial-group +.upd)
==
::
++ handle-add
|= [group=resource =md-resource:store =metadatum:store]
^- (quip card _state)
:- %- send-diff:mc
[%add group md-resource metadatum]
%= state
associations
(~(put by associations) md-resource [group metadatum])
::
app-indices
%+ ~(put ju app-indices)
app-name.md-resource
[group resource.md-resource]
::
resource-indices
(~(put by resource-indices) md-resource group)
::
group-indices
(~(put ju group-indices) group md-resource)
==
::
++ handle-edit
|= [group=resource =md-resource:store =edit-field:store]
^- (quip card _state)
=/ [new-group=resource =metadatum:store]
~| %no-assoc-for-edit
(~(got by associations) md-resource)
~| %cant-reassign-groups
?> =(new-group group)
=. metadatum
?- -.edit-field
%title metadatum(title title.edit-field)
%description metadatum(description description.edit-field)
%color metadatum(color color.edit-field)
%picture metadatum(picture url.edit-field)
%hidden metadatum(hidden hidden.edit-field)
%preview metadatum(preview preview.edit-field)
%vip metadatum(vip vip.edit-field)
==
:- (send-diff:mc %add group md-resource metadatum)
%_ state
associations (~(put by associations) md-resource group metadatum)
==
::
++ handle-remove
|= [group=resource =md-resource:store]
^- (quip card _state)
:- (send-diff:mc [%remove group md-resource])
%= state
associations
(~(del by associations) md-resource)
::
app-indices
%+ ~(del ju app-indices)
app-name.md-resource
[group resource.md-resource]
::
resource-indices
(~(del by resource-indices) md-resource)
::
group-indices
(~(del ju group-indices) group md-resource)
==
::
++ handle-initial-group
|= [group=resource =associations:store]
=/ assocs=(list [=md-resource:store grp=resource =metadatum:store])
~(tap by associations)
:- (send-diff:mc %initial-group group associations)
|-
?~ assocs
state
=, assocs
?> =(group grp.i)
=^ cards state
(handle-add group [md-resource metadatum]:i)
$(assocs t)
--
::
++ poke-import
|= arc=*
^- (quip card _state)
|^
=^ cards state
(on-load:mc !>([%9 (remake-metadata ;;(tree-metadata +.arc))]))
:_ state
%+ weld cards
%+ turn ~(tap in ~(key by group-indices))
|= rid=resource
%- poke-our
?: =(entity.rid our.bowl)
:- %metadata-push-hook
push-hook-action+!>([%add rid])
:- %metadata-pull-hook
pull-hook-action+!>([%add [entity .]:rid])
::
++ poke-our
|= [app=term =cage]
^- card
[%pass / %agent [our.bowl app] %poke cage]
::
+$ tree-metadata
$: associations=(tree [md-resource:store [resource metadatum:store]])
~
==
::
++ remake-metadata
|= tm=tree-metadata
^- base-state-3
:* (remake-map associations.tm)
~
==
--
--
::
++ on-watch
|= =path
^- (quip card _this)
@ -174,7 +301,7 @@
=/ cards=(list card)
?+ path (on-watch:def path)
[%all ~]
(give %metadata-update-1 !>([%associations associations]))
(give %metadata-update-2 !>([%associations associations]))
::
[%updates ~]
~
@ -182,7 +309,7 @@
[%app-name @ ~]
=/ =app-name:store i.t.path
=/ app-indices (metadata-for-app:mc app-name)
(give %metadata-update-1 !>([%associations app-indices]))
(give %metadata-update-2 !>([%associations app-indices]))
==
[cards this]
::
@ -418,109 +545,6 @@
ship+path.md-resource
[[path [%graph new-path]] m(module app)]
--
::
:: TODO: refactor into a |^ inside the agent core
++ poke-metadata-update
|= upd=update:store
^- (quip card _state)
?> (team:title [our src]:bowl)
?+ -.upd !!
%add (handle-add +.upd)
%remove (handle-remove +.upd)
%initial-group (handle-initial-group +.upd)
==
::
:: TODO: refactor into a |^ inside the agent core
++ poke-import
|= arc=*
^- (quip card _state)
|^
=^ cards state
(on-load !>([%9 (remake-metadata ;;(tree-metadata +.arc))]))
:_ state
%+ weld cards
%+ turn ~(tap in ~(key by group-indices))
|= rid=resource
%- poke-our
?: =(entity.rid our.bowl)
:- %metadata-push-hook
push-hook-action+!>([%add rid])
:- %metadata-pull-hook
pull-hook-action+!>([%add [entity .]:rid])
::
++ poke-our
|= [app=term =cage]
^- card
[%pass / %agent [our.bowl app] %poke cage]
::
+$ tree-metadata
$: associations=(tree [md-resource:store [resource metadatum:store]])
~
==
::
++ remake-metadata
|= tm=tree-metadata
^- base-state-3
:* (remake-map associations.tm)
~
==
--
::
++ handle-add
|= [group=resource =md-resource:store =metadatum:store]
^- (quip card _state)
:- %- send-diff
[%add group md-resource metadatum]
%= state
associations
(~(put by associations) md-resource [group metadatum])
::
app-indices
%+ ~(put ju app-indices)
app-name.md-resource
[group resource.md-resource]
::
resource-indices
(~(put by resource-indices) md-resource group)
::
group-indices
(~(put ju group-indices) group md-resource)
==
::
++ handle-remove
|= [group=resource =md-resource:store]
^- (quip card _state)
:- (send-diff [%remove group md-resource])
%= state
associations
(~(del by associations) md-resource)
::
app-indices
%+ ~(del ju app-indices)
app-name.md-resource
[group resource.md-resource]
::
resource-indices
(~(del by resource-indices) md-resource)
::
group-indices
(~(del ju group-indices) group md-resource)
==
::
++ handle-initial-group
|= [group=resource =associations:store]
=/ assocs=(list [=md-resource:store grp=resource =metadatum:store])
~(tap by associations)
:- (send-diff %initial-group group associations)
|-
?~ assocs
state
=, assocs
?> =(group grp.i)
=^ cards state
(handle-add group [md-resource metadatum]:i)
$(assocs t)
::
++ metadata-for-app
|= =app-name:store
^- associations:store
@ -556,6 +580,6 @@
++ update-subscribers
|= [pax=path =update:store]
^- (list card)
[%give %fact ~[pax] %metadata-update-1 !>(update)]~
[%give %fact ~[pax] %metadata-update-2 !>(update)]~
--
--

View File

@ -37,6 +37,17 @@
[%metadata (^metadatum metadatum)]
==
::
++ edit-field
|= edt=^edit-field
^- json
%+ frond -.edt
^- json
?- -.edt
%color [%s `@t`(scot %ux color.edt)]
?(%title %description %picture %vip) [%s `@t`+.edt]
?(%preview %hidden) [%b `?`+.edt]
==
::
++ metadatum
|= met=^metadatum
^- json
@ -85,6 +96,16 @@
[%resource s+(enjs-path:resource resource.resource.upd)]
[%metadata (metadatum metadatum.upd)]
==
::
%edit
:- %edit
%- pairs
:~ [%group s+(enjs-path:resource group.upd)]
[%app-name s+app-name.resource.upd]
[%resource s+(enjs-path:resource resource.resource.upd)]
[%edit (edit-field edit-field.upd)]
==
::
%updated-metadata
:- %add
%- pairs
@ -136,6 +157,25 @@
:~ [%add add]
[%remove remove]
[%initial-group initial-group]
[%edit edit]
==
::
++ edit
%- ot
:~ [%group dejs-path:resource]
[%resource md-resource]
[%edit edit-field]
==
::
++ edit-field
%- of
:~ [%title so]
[%description so]
[%color nu]
[%picture so]
[%preview bo]
[%hidden bo]
[%vip vip]
==
::
++ initial-group

View File

@ -30,7 +30,7 @@
|= =vase
^- (list resource)
=/ =update:store !<(update:store vase)
?. ?=(?(%add %remove %initial-group) -.update) ~
?. ?=(?(%add %remove %initial-group %edit) -.update) ~
~[group.update]
::
++ app-paths-from-group

View File

@ -1,15 +1,22 @@
/+ store=metadata-store
|_ =update:store
|_ =update:one:store
++ grad %noun
++ grow
|%
++ noun update
++ json (update:enjs:store update)
++ metadata-update-2
^- update:store
update
--
::
++ grab
|%
++ noun update:store
++ json action:dejs:store
++ noun update:one:store
:: This is ok, we don't send %edit over the wire yet.
++ metadata-update-2
|= upd=update:store
^- update:one:store
?< ?=(%edit -.upd)
upd
--
--

View File

@ -0,0 +1,15 @@
/+ store=metadata-store
|_ =update:store
++ grad %noun
++ grow
|%
++ noun update
++ json (update:enjs:store update)
--
::
++ grab
|%
++ noun update:store
++ json update:dejs:store
--
--

View File

@ -44,6 +44,16 @@
[%empty ~]
==
::
+$ edit-field
$% [%title title=cord]
[%description description=cord]
[%color color=@ux]
[%picture =url]
[%preview preview=?]
[%hidden hidden=?]
[%vip vip=vip-metadata]
==
::
+$ metadatum
$: title=cord
description=cord
@ -60,6 +70,7 @@
+$ action
$% [%add group=resource resource=md-resource =metadatum]
[%remove group=resource resource=md-resource]
[%edit group=resource resource=md-resource =edit-field]
[%initial-group group=resource =associations]
==
::
@ -79,6 +90,18 @@
==
==
:: historical
++ one
|%
::
+$ action
$~ [%remove *resource *md-resource]
$< %edit ^action
::
+$ update
$~ [%remove *resource *md-resource]
$< %edit ^update
::
--
++ zero
|%
::

View File

@ -46,7 +46,7 @@
(poke-our %graph-push-hook %push-hook-action !>([%add feed-rid]))
;< ~ bind:m
%+ poke-our %metadata-push-hook
:- %metadata-update-1
:- %metadata-update-2
!> ^- action:met
:^ %add
group.action
@ -54,7 +54,7 @@
metadatum(feed.config ``[%graph feed-rid])
;< ~ bind:m
%+ poke-our %metadata-push-hook
:- %metadata-update-1
:- %metadata-update-2
!> ^- action:met
:^ %add
group.action

View File

@ -78,7 +78,7 @@
=/ met-action=action:met
[%add group graph+rid.action metadatum]
;< ~ bind:m
(poke-our %metadata-push-hook metadata-update-1+!>(met-action))
(poke-our %metadata-push-hook metadata-update-2+!>(met-action))
::
:: Send invites
::

View File

@ -41,7 +41,7 @@
(poke-our %graph-push-hook %push-hook-action !>([%remove rid]))
;< ~ bind:m
%+ poke-our %metadata-push-hook
:- %metadata-update-1
:- %metadata-update-2
!> ^- action:metadata
[%remove group-rid [%graph rid]]
(pure:m ~)

View File

@ -31,7 +31,7 @@
==
;< ~ bind:m
%+ poke-our %metadata-push-hook
:- %metadata-update-1
:- %metadata-update-2
!> ^- action:met
:^ %add
group.action

View File

@ -5,7 +5,7 @@ import {
Text
} from '@tlon/indigo-react';
import { addTag, Association, Group, metadataUpdate, PermVariation, removeTag } from '@urbit/api';
import { addTag, Association, Group, PermVariation, removeTag, metadataEdit } from '@urbit/api';
import { Form, Formik } from 'formik';
import _ from 'lodash';
import React from 'react';
@ -107,7 +107,7 @@ export function GraphPermissions(props: GraphPermissionsProps) {
};
const allWriters = Array.from(writers).map(w => `~${w}`);
if (values.readerComments !== readerComments) {
await airlock.poke(metadataUpdate(association, {
await airlock.poke(metadataEdit(association, {
vip: values.readerComments ? 'reader-comments' : ''
}));
}

View File

@ -3,7 +3,8 @@ import {
Label, ManagedTextInputField as Input,
Text
} from '@tlon/indigo-react';
import { Association, metadataUpdate } from '@urbit/api';
import _ from 'lodash';
import { Association, metadataEdit } from '@urbit/api';
import { Form, Formik } from 'formik';
import React from 'react';
import { uxToHex } from '~/logic/lib/util';
@ -32,9 +33,13 @@ export function ChannelDetails(props: ChannelDetailsProps) {
};
const onSubmit = async (values: FormSchema, actions) => {
const { title, description } = values;
const color = uxToHex(values.color);
await airlock.poke(metadataUpdate(association, { title, color, description }));
values.color = uxToHex(values.color);
const promises = _.compact(_.map(values, (value,k) => {
return value !== initialValues[k]
? airlock.poke(metadataEdit(association, { [k]: value }))
: null;
}));
await Promise.all(promises);
actions.setStatus({ success: null });
};

View File

@ -8,7 +8,7 @@ import {
leaveGraph,
metadataRemove
} from '@urbit/api';
import React, { useCallback, useRef } from 'react';
import React, { useCallback } from 'react';
import { Link, useHistory } from 'react-router-dom';
import { isChannelAdmin, isHost } from '~/logic/lib/group';
import { useHashLink } from '~/logic/lib/useHashLink';
@ -31,7 +31,6 @@ interface ChannelPopoverRoutesProps {
export function ChannelPopoverRoutes(props: ChannelPopoverRoutesProps) {
const { association, group } = props;
useHashLink();
const overlayRef = useRef<HTMLElement>();
const history = useHistory();
const onDismiss = useCallback(() => {
@ -63,7 +62,6 @@ export function ChannelPopoverRoutes(props: ChannelPopoverRoutesProps) {
height="100%"
width="100%"
spacing={[3, 5, 7]}
ref={overlayRef}
dismiss={onDismiss}
>
<Row

View File

@ -4,9 +4,10 @@ import {
ManagedToggleSwitchField as Checkbox,
Text
} from '@tlon/indigo-react';
import { changePolicy, Enc, metadataUpdate } from '@urbit/api';
import _ from 'lodash';
import { changePolicy, Enc } from '@urbit/api';
import { Group, GroupPolicy } from '@urbit/api/groups';
import { Association } from '@urbit/api/metadata';
import { Association, metadataEdit, MetadataEditField } from '@urbit/api/metadata';
import { Form, Formik, FormikHelpers } from 'formik';
import React from 'react';
import * as Yup from 'yup';
@ -58,16 +59,26 @@ export function GroupAdminSettings(props: GroupAdminSettingsProps) {
actions: FormikHelpers<FormSchema>
) => {
try {
const { title, description, picture, color, isPrivate, adminMetadata } = values;
const { color, isPrivate, adminMetadata } = values;
const update = (upd: MetadataEditField) =>
airlock.poke(metadataEdit(association, upd));
const uxColor = uxToHex(color);
const vip = adminMetadata ? '' : 'member-metadata';
await airlock.poke(metadataUpdate(props.association, {
title,
description,
picture,
color: uxColor,
vip
const promises = _.compact(_.map(['title', 'description', 'picture'] as const,
(k) => {
const edit: MetadataEditField = { [k]: values[k] };
return (values[k] !== initialValues[k])
? update(edit)
: null;
}));
if(vip !== metadata.vip) {
promises.push(update({ vip }));
}
if(uxColor !== metadata.color) {
promises.push(update({ color: uxColor }));
}
await Promise.all(promises);
if (isPrivate !== currentPrivate) {
const resource = resourceFromPath(props.association.group);
const newPolicy: Enc<GroupPolicy> = isPrivate

View File

@ -1,5 +1,5 @@
import { Col, Icon, Row, Text } from '@tlon/indigo-react';
import { Association, Group, metadataRemove, metadataUpdate } from '@urbit/api';
import { Association, Group, metadataRemove, metadataEdit } from '@urbit/api';
import React, { useCallback } from 'react';
import { resourceFromPath, roleForShip } from '~/logic/lib/group';
import { getModuleIcon, GraphModule } from '~/logic/lib/util';
@ -22,7 +22,8 @@ export function GroupChannelSettings(props: GroupChannelSettingsProps) {
const onChange = useCallback(
async (resource: string, preview: boolean) => {
await airlock.poke(metadataUpdate(associations.graph[resource], { preview }));
const association = associations.graph[resource];
await airlock.poke(metadataEdit(association, { preview }));
},
[associations.graph]
);

View File

@ -1,5 +1,5 @@
import { BaseLabel, Col, Label, Text } from '@tlon/indigo-react';
import { Association, createGroupFeed, disableGroupFeed, Group, metadataUpdate, PermVariation, resourceFromPath } from '@urbit/api';
import { Association, createGroupFeed, disableGroupFeed, Group, metadataEdit, PermVariation, resourceFromPath } from '@urbit/api';
import { Form, Formik, FormikHelpers } from 'formik';
import React from 'react';
import useMetadataState from '~/logic/state/metadata';
@ -46,7 +46,11 @@ export function GroupFeedSettings(props: {
values: FormSchema,
actions: FormikHelpers<FormSchema>
) => {
await airlock.poke(metadataUpdate(feedAssoc, { vip: values.permissions.trim() as PermVariation }));
await airlock.poke(
metadataEdit(feedAssoc, {
vip: values.permissions.trim() as PermVariation
})
);
actions.setStatus({ success: null });
};

View File

@ -1,5 +1,5 @@
import { AppName, Path, Poke, uxToHex, PatpNoSig } from '../lib';
import { Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove } from './types';
import { Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove, MetadataEditField, MetadataUpdateEdit } from './types';
export const METADATA_UPDATE_VERSION = 1;
@ -59,6 +59,25 @@ export const remove = (
export { remove as metadataRemove };
export const edit = (
association: Association,
edit: MetadataEditField
): Poke<MetadataUpdateEdit> => metadataAction({
edit: {
group: association.group,
resource: {
resource: association.resource,
'app-name': association['app-name']
},
edit
}
});
export { edit as metadataEdit };
/**
* @deprecated use {@link edit} instead
*/
export const update = (
association: Association,
newMetadata: Partial<Metadata>

View File

@ -4,7 +4,8 @@ export type MetadataUpdate =
MetadataUpdateInitial
| MetadataUpdateAdd
| MetadataUpdateUpdate
| MetadataUpdateRemove;
| MetadataUpdateRemove
| MetadataUpdateEdit;
export interface MetadataUpdateInitial {
associations: ResourceAssociations;
@ -22,6 +23,15 @@ export type MetadataUpdateUpdate = {
update: AssociationPoke;
}
export interface MetadataUpdateEdit {
edit: {
resource: MdResource;
edit: MetadataEditField;
}
}
export type MetadataEditField = Partial<Omit<Metadata, 'config' | 'creator' | 'date-created'>>;
export type MetadataUpdateRemove = {
remove: {
resource: MdResource;