mirror of
https://github.com/urbit/shrub.git
synced 2024-12-01 06:35:32 +03:00
Merge pull request #2777 from urbit/ixv/publish-groupify
publish: groupify notebooks
This commit is contained in:
commit
a810468dcf
@ -1702,8 +1702,107 @@
|
||||
:~ [%give %fact [/primary]~ %publish-primary-delta !>(act)]
|
||||
[%give %fact [/publishtile]~ %json !>(jon)]
|
||||
==
|
||||
:: %groupify
|
||||
::
|
||||
%groupify
|
||||
?. (team:title our.bol src.bol)
|
||||
~|("action not permitted" !!)
|
||||
=/ book (~(get by books) our.bol book.act)
|
||||
?~ book
|
||||
~|("nonexistent notebook: {<book.act>}" !!)
|
||||
::
|
||||
=/ old-write writers.u.book
|
||||
=/ old-read subscribers.u.book
|
||||
?> ?=([%'~' ^] old-write)
|
||||
=/ destroy-old-groups=(list card)
|
||||
:~ (group-poke [%unbundle old-write])
|
||||
(group-poke [%unbundle old-read])
|
||||
(group-hook-poke [%remove old-write])
|
||||
(group-hook-poke [%remove old-read])
|
||||
(perm-hook-poke [%remove old-write])
|
||||
(perm-hook-poke [%remove old-read])
|
||||
==
|
||||
::
|
||||
?~ target.act
|
||||
:: create new group from subscribers
|
||||
::
|
||||
=. writers.u.book (slag 1 writers.u.book)
|
||||
=. subscribers.u.book writers.u.book
|
||||
=/ del=notebook-delta [%edit-book our.bol book.act u.book]
|
||||
:_ state(books (~(put by books) [our.bol book.act] u.book))
|
||||
%+ weld destroy-old-groups
|
||||
^- (list card)
|
||||
:~ [%give %fact [/notebook/[book.act]]~ %publish-notebook-delta !>(del)]
|
||||
[%give %fact [/primary]~ %publish-primary-delta !>(del)]
|
||||
%- contact-view-create
|
||||
:* writers.u.book
|
||||
(get-subscribers book.act)
|
||||
title.u.book
|
||||
description.u.book
|
||||
==
|
||||
%- metadata-poke
|
||||
:* %add
|
||||
writers.u.book
|
||||
[%publish /(scot %p our.bol)/[book.act]]
|
||||
title.u.book
|
||||
description.u.book
|
||||
0x0
|
||||
date-created.u.book
|
||||
our.bol
|
||||
==
|
||||
==
|
||||
::
|
||||
?> ?=(^ u.target.act)
|
||||
=. writers.u.book u.target.act
|
||||
=. subscribers.u.book u.target.act
|
||||
=/ group-host=@p (slav %p i.u.target.act)
|
||||
::
|
||||
=/ scry-pax :(weld /=group-store/(scot %da now.bol) u.target.act /noun)
|
||||
=/ old-group=(set @p) (need .^((unit (set @p)) %gx scry-pax))
|
||||
=/ dif-peeps=(set @p) (~(dif in (get-subscribers book.act)) old-group)
|
||||
::
|
||||
=/ del=notebook-delta [%edit-book our.bol book.act u.book]
|
||||
:_ state(books (~(put by books) [our.bol book.act] u.book))
|
||||
%+ weld
|
||||
%+ weld destroy-old-groups
|
||||
^- (list card)
|
||||
:~ [%give %fact [/notebook/[book.act]]~ %publish-notebook-delta !>(del)]
|
||||
[%give %fact [/primary]~ %publish-primary-delta !>(del)]
|
||||
%- metadata-poke
|
||||
:* %add
|
||||
writers.u.book
|
||||
[%publish /(scot %p our.bol)/[book.act]]
|
||||
title.u.book
|
||||
description.u.book
|
||||
0x0
|
||||
date-created.u.book
|
||||
our.bol
|
||||
==
|
||||
==
|
||||
?: ?& inclusive.act
|
||||
=(group-host our.bol)
|
||||
==
|
||||
:: add all subscribers to group
|
||||
::
|
||||
[(group-poke [%add dif-peeps u.target.act])]~
|
||||
:: kick subscribers who are not already in group
|
||||
::
|
||||
%+ turn ~(tap in dif-peeps)
|
||||
|= who=@p
|
||||
^- card
|
||||
[%give %kick [/notebook/[book.act]]~ `who]
|
||||
==
|
||||
::
|
||||
++ get-subscribers
|
||||
|= book=@tas
|
||||
^- (set @p)
|
||||
%+ roll ~(val by sup.bol)
|
||||
|= [[who=@p pax=path] out=(set @p)]
|
||||
^- (set @p)
|
||||
?. ?=([%notebook @ ~] pax) out
|
||||
?. =(book i.t.pax) out
|
||||
(~(put in out) who)
|
||||
::
|
||||
++ get-notebook
|
||||
|= [host=@p book-name=@tas sty=_state]
|
||||
^- (unit notebook)
|
||||
@ -1732,6 +1831,11 @@
|
||||
[%give %fact [/publishtile]~ %json !>(jon)]
|
||||
==
|
||||
::
|
||||
++ metadata-poke
|
||||
|= act=metadata-action
|
||||
^- card
|
||||
[%pass / %agent [our.bol %metadata-hook] %poke %metadata-action !>(act)]
|
||||
::
|
||||
++ emit-metadata
|
||||
|= del=metadata-delta
|
||||
^- (list card)
|
||||
@ -1762,11 +1866,6 @@
|
||||
^- (list card)
|
||||
[(metadata-poke [%add group-path [%publish app-path] metadata])]~
|
||||
::
|
||||
++ metadata-poke
|
||||
|= act=metadata-action
|
||||
^- card
|
||||
[%pass / %agent [our.bol %metadata-hook] %poke %metadata-action !>(act)]
|
||||
::
|
||||
++ metadata-scry
|
||||
|= [group-path=path app-path=path]
|
||||
^- (unit metadata)
|
||||
|
@ -32,6 +32,7 @@
|
||||
subscribe+subscribe
|
||||
unsubscribe+unsubscribe
|
||||
read+read
|
||||
groupify+groupify
|
||||
==
|
||||
::
|
||||
++ new-book
|
||||
@ -114,6 +115,12 @@
|
||||
book+so
|
||||
note+so
|
||||
==
|
||||
++ groupify
|
||||
%- ot
|
||||
:~ book+so
|
||||
target+(mu pa)
|
||||
inclusive+bo
|
||||
==
|
||||
++ group-info
|
||||
%- ot
|
||||
:~ group-path+pa
|
||||
|
@ -25,6 +25,8 @@
|
||||
[%unsubscribe who=@p book=@tas]
|
||||
::
|
||||
[%read who=@p book=@tas note=@tas]
|
||||
::
|
||||
[%groupify book=@tas target=(unit path) inclusive=?]
|
||||
==
|
||||
::
|
||||
+$ comment comment-3
|
||||
|
@ -99,7 +99,7 @@ export class Notebook extends Component {
|
||||
list={notesList}
|
||||
host={props.ship}
|
||||
notebookName={props.book}
|
||||
contacts={props.contacts}
|
||||
contacts={props.notebookContacts}
|
||||
/>
|
||||
break;
|
||||
case "about":
|
||||
@ -119,6 +119,8 @@ export class Notebook extends Component {
|
||||
book={this.props.book}
|
||||
notebook={notebook}
|
||||
groups={this.props.groups}
|
||||
contacts={this.props.contacts}
|
||||
associations={this.props.associations}
|
||||
history={this.props.history}/>
|
||||
break;
|
||||
default:
|
||||
@ -126,8 +128,8 @@ export class Notebook extends Component {
|
||||
}
|
||||
|
||||
// displaying nicknames, sigil colors for contacts
|
||||
let contact = !!(props.ship.substr(1) in props.contacts)
|
||||
? props.contacts[props.ship.substr(1)] : false;
|
||||
let contact = !!(props.ship.substr(1) in props.notebookContacts)
|
||||
? props.notebookContacts[props.ship.substr(1)] : false;
|
||||
let name = props.ship;
|
||||
if (contact) {
|
||||
name = (contact.nickname.length > 0)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { writeText } from '../../lib/util';
|
||||
import { Spinner } from './icons/icon-spinner';
|
||||
import { InviteSearch } from '/components/lib/invite-search';
|
||||
|
||||
export class Settings extends Component {
|
||||
constructor(props){
|
||||
@ -10,12 +11,16 @@ export class Settings extends Component {
|
||||
description: "",
|
||||
comments: false,
|
||||
disabled: false,
|
||||
type: "Editing"
|
||||
type: "Editing",
|
||||
targetGroup: null,
|
||||
inclusive: false,
|
||||
}
|
||||
this.deleteNotebook = this.deleteNotebook.bind(this);
|
||||
this.changeTitle = this.changeTitle.bind(this);
|
||||
this.changeDescription = this.changeDescription.bind(this);
|
||||
this.changeComments = this.changeComments.bind(this);
|
||||
this.changeTargetGroup = this.changeTargetGroup.bind(this);
|
||||
this.changeInclusive = this.changeInclusive.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -84,6 +89,111 @@ export class Settings extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
changeTargetGroup(target) {
|
||||
if (target.groups.length === 1) {
|
||||
this.setState({ targetGroup: target.groups[0] });
|
||||
} else {
|
||||
this.setState({ targetGroup: null });
|
||||
}
|
||||
}
|
||||
|
||||
changeInclusive(event) {
|
||||
this.setState({ inclusive: !!event.target.checked });
|
||||
}
|
||||
|
||||
groupifyNotebook() {
|
||||
const { props, state } = this;
|
||||
|
||||
this.setState({
|
||||
disabled: true,
|
||||
type: 'Converting'
|
||||
}, (() => {
|
||||
window.api.action("publish", "publish-action", {
|
||||
groupify: {
|
||||
book: props.book,
|
||||
target: state.targetGroup,
|
||||
inclusive: state.inclusive,
|
||||
}
|
||||
}).then(() => this.setState({disabled: false}));
|
||||
}));
|
||||
}
|
||||
|
||||
renderGroupify() {
|
||||
const { props, state } = this;
|
||||
|
||||
const owner = (props.host.slice(1) === window.ship);
|
||||
|
||||
const ownedUnmanaged =
|
||||
owner &&
|
||||
props.notebook['writers-group-path'].slice(0, 3) === '/~/';
|
||||
|
||||
if (!ownedUnmanaged) {
|
||||
return null;
|
||||
} else {
|
||||
// don't give the option to make inclusive if we don't own the target
|
||||
// group
|
||||
let targetOwned = (state.targetGroup)
|
||||
? state.targetGroup.slice(0, window.ship.length+3) === `/~${window.ship}/`
|
||||
: false;
|
||||
let inclusiveToggle = <div/>
|
||||
if (targetOwned) {
|
||||
//TODO toggle component into /lib
|
||||
let inclusiveClasses = state.inclusive
|
||||
? "relative checked bg-green2 br3 h1 toggle v-mid z-0"
|
||||
: "relative bg-gray4 bg-gray1-d br3 h1 toggle v-mid z-0";
|
||||
inclusiveToggle = (
|
||||
<div className="mt4">
|
||||
<input
|
||||
type="checkbox"
|
||||
style={{ WebkitAppearance: "none", width: 28 }}
|
||||
className={inclusiveClasses}
|
||||
onChange={this.changeInclusive}
|
||||
/>
|
||||
<span className="dib f9 white-d inter ml3">
|
||||
Add all members to group
|
||||
</span>
|
||||
<p className="f9 gray2 pt1" style={{ paddingLeft: 40 }}>
|
||||
Add notebook members to the group if they aren't in it yet
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={"w-100 fl mt3 mb3"} style={{maxWidth: "29rem"}}>
|
||||
<p className="f8 mt3 lh-copy db">Convert Notebook</p>
|
||||
<p className="f9 gray2 db mb4">
|
||||
Convert this notebook into a group with associated chat, or select a
|
||||
group to add this notebook to.
|
||||
</p>
|
||||
<InviteSearch
|
||||
groups={props.groups}
|
||||
contacts={props.contacts}
|
||||
associations={props.associations}
|
||||
groupResults={true}
|
||||
shipResults={false}
|
||||
invites={{
|
||||
groups: state.targetGroup ? [state.targetGroup] : [],
|
||||
ships: []
|
||||
}}
|
||||
setInvite={this.changeTargetGroup}
|
||||
/>
|
||||
{inclusiveToggle}
|
||||
<button
|
||||
onClick={this.groupifyNotebook.bind(this)}
|
||||
className={"dib f9 black gray4-d bg-gray0-d ba pa2 mt4 b--black b--gray1-d pointer"}
|
||||
disabled={this.state.disabled}>
|
||||
Convert to group
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
render() {
|
||||
let commentsSwitchClasses = (this.state.comments)
|
||||
? "relative checked bg-green2 br3 h1 toggle v-mid z-0"
|
||||
@ -115,6 +225,7 @@ export class Settings extends Component {
|
||||
return (
|
||||
<div className="flex-column">
|
||||
{copyShortcode}
|
||||
{this.renderGroupify()}
|
||||
<p className="f9 mt6 lh-copy db">Delete Notebook</p>
|
||||
<p className="f9 gray2 db mb4">
|
||||
Permanently delete this notebook. (All current members will no
|
||||
|
@ -135,6 +135,7 @@ export class Root extends Component {
|
||||
|
||||
let bookGroupPath =
|
||||
state.notebooks[ship][notebook]["subscribers-group-path"];
|
||||
|
||||
let notebookContacts = (bookGroupPath in contacts)
|
||||
? contacts[bookGroupPath] : {};
|
||||
|
||||
@ -181,7 +182,9 @@ export class Root extends Component {
|
||||
ship={ship}
|
||||
book={notebook}
|
||||
groups={state.groups}
|
||||
contacts={notebookContacts}
|
||||
contacts={contacts}
|
||||
notebookContacts={notebookContacts}
|
||||
associations={associations.contacts}
|
||||
sidebarShown={state.sidebarShown}
|
||||
popout={popout}
|
||||
permissions={state.permissions}
|
||||
@ -264,4 +267,4 @@ export class Root extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default Root;
|
||||
export default Root;
|
||||
|
@ -133,6 +133,10 @@ export class PrimaryReducer {
|
||||
state.notebooks[host][book]["num-notes"] = json[host][book]["num-notes"];
|
||||
state.notebooks[host][book]["num-unread"] = json[host][book]["num-unread"];
|
||||
state.notebooks[host][book]["title"] = json[host][book]["title"];
|
||||
state.notebooks[host][book]["writers-group-path"] =
|
||||
json[host][book]["writers-group-path"];
|
||||
state.notebooks[host][book]["subscribers-group-path"] =
|
||||
json[host][book]["subscribers-group-path"];
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user