Skip to content

Commit

Permalink
implements making collections
Browse files Browse the repository at this point in the history
  • Loading branch information
zippy committed Dec 29, 2023
1 parent 77b63c9 commit d559b93
Show file tree
Hide file tree
Showing 11 changed files with 312 additions and 85 deletions.
5 changes: 2 additions & 3 deletions dnas/how/zomes/coordinator/how/src/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,10 @@ pub fn advance_state(input: AdvanceStateInput) -> ExternResult<EntryHashB64> {

.ok_or(wasm_error!(WasmErrorInner::Guest(String::from("Malformed unit"))))?;
let mut document = input.document;
// let now = Timestamp::now().as_micros();
// document.meta.insert("timestamp".to_string(),now.to_string());
let now = sys_time()?.as_micros(); // we need to do this to make sure that content is distinct in case of moving state back and forth for history.
document.meta.insert("timestamp".to_string(),now.to_string());
let new_document = UpdateDocumentInput {
hash: input.document_hash.clone(), path: unit.path_str()?, document };
debug!("Updating Doc {:?}", new_document);
let new_doc_hash = update_document(new_document)?;

delete_unit_links(hash.clone(), unit.tree_paths())?;
Expand Down
79 changes: 79 additions & 0 deletions ui/src/elements/how-collect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { css, html, LitElement } from "lit";
import { query } from "lit/decorators.js";
import { sharedStyles } from "../sharedStyles";
import { ScopedElementsMixin } from "@open-wc/scoped-elements";
import {
Button,
Dialog,
TextField,
} from "@scoped-elements/material-web";
import { Section } from "../types";

/**
* @element how-collect-dialog
*/
export class HowCollect extends ScopedElementsMixin(LitElement) {

@query('#collect-dialog')
_dialogElem!: Dialog;
@query('#version-field')
_versionField!: TextField;

private collectionDef: Section | undefined

open(def: Section) {
this._versionField.value = ""
this.collectionDef = def
this._dialogElem!.open = true
}

private async handleOk(e: any) {
if (!this._versionField.validity.valid) {
this._versionField.reportValidity()
return
}

this.dispatchEvent(new CustomEvent('collect', { detail: {version: this._versionField.value, def:this.collectionDef}, bubbles: true, composed: true }));
this._dialogElem!.close()
}
render() {
return html`
<mwc-dialog id="collect-dialog" heading="Collect">
<mwc-textfield dialogInitialFocus type="text"
@input=${() => (this.shadowRoot!.getElementById("version-field") as TextField).reportValidity()}
id="version-field" minlength="1" maxlength="64" label="Version" autoValidate=true required></mwc-textfield>
<mwc-button
id="primary-action-button"
slot="primaryAction"
@click=${this.handleOk}
>ok</mwc-button
>
<mwc-button slot="secondaryAction" dialogAction="cancel"
>cancel</mwc-button
>
</mwc-dialog>
`;
}

static get scopedElements() {
return {
"mwc-button": Button,
"mwc-dialog": Dialog,
"mwc-textfield": TextField,
};
}
static get styles() {
return [
sharedStyles,
css`
:host {
--mdc-dialog-max-width: 1000px;
}
.message {
max-width: 300px;
}
`,
];
}
}
2 changes: 1 addition & 1 deletion ui/src/elements/how-confirm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {

const DEFAULT_CONFIRM_MESSAGE = "Please confirm!"
/**
* @element how-new-section-dialog
* @element how-confirm-dialog
*/
export class HowConfirm extends ScopedElementsMixin(LitElement) {

Expand Down
119 changes: 77 additions & 42 deletions ui/src/elements/how-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { StoreSubscriber } from "@holochain-open-dev/stores";

import {sharedStyles} from "../sharedStyles";
import {EntryHashB64, encodeHashToBase64} from "@holochain/client";
import {howContext, Section, SectionType, SourceManual, Document, DocType, HilightRange, CommentInfo, Comment, CommentStatus, MarkTypes, MarkDocumentInput, CommentAction, applyApprovedComments, CommentStats, DocumentStats, DocumentAction, VoteAction, ApprovalAction, parseAgentArray, Dictionary} from "../types";
import {howContext, Section, SectionType, SourceManual, Document, DocType, HilightRange, CommentInfo, Comment, CommentStatus, MarkTypes, MarkDocumentInput, CommentAction, applyApprovedComments, CommentStats, DocumentStats, DocumentAction, VoteAction, ApprovalAction, Dictionary, Unit} from "../types";
import {HowStore} from "../how.store";
import {ScopedElementsMixin} from "@open-wc/scoped-elements";
import {
Expand All @@ -22,6 +22,7 @@ import { HowCommentBox } from "./how-comment-box";
import { ActionHash } from "@holochain/client";
import { HowConfirm } from "./how-confirm";
import { CommentControl, Control } from "../controls";
import {until} from 'lit-html/directives/until.js';

/**
* @element how-document
Expand All @@ -42,8 +43,20 @@ import { CommentControl, Control } from "../controls";
@state() overlapping : Comment[] | undefined
@state() commentStats : CommentStats | undefined;
@state() availbleCollectionSections : Array<string> = ["host_fn specs"]
@state() collectionDefs : Array<Section> = []

_units = new StoreSubscriber(this, () => this._store.units);

private selectedCommentText: string = ""

async updated(changedProperties:any) {
for (const [prop,_] of changedProperties) {
if (prop === 'currentDocumentEh' && prop.currentDocumentEh != this.currentDocumentEh) {
this.collectionDefs = await this._store.collectionDefs(this.currentDocumentEh)
break;
}
}
}

@query('how-new-section-dialog')
private _newSectionDialog!: HowNewSectionDialog;
Expand All @@ -59,14 +72,14 @@ import { CommentControl, Control } from "../controls";
this.dispatchEvent(new CustomEvent('document-updated', { detail: newDocumentHash, bubbles: true, composed: true }));
}

async addSection(e: any) {
const section: Section = {
name: e.detail.name,
contentType: e.detail.contentType,
sectionType:e.detail.sectionType,
sourcePath: SourceManual,
content: ""
}
async deleteSection(section:Section, index:number) {
const document = this._documents.value[this.currentDocumentEh]
document.content.splice(index,1)
const newDocumentHash = await this._store.updateDocument(this.currentDocumentEh, document);
this.dispatchEvent(new CustomEvent('document-updated', { detail: newDocumentHash, bubbles: true, composed: true }));
}

async addSection(section: Section) {
const document = this._documents.value[this.currentDocumentEh]
document.content.push(section)
const newDocumentHash = await this._store.updateDocument(this.currentDocumentEh, document);
Expand Down Expand Up @@ -384,7 +397,7 @@ import { CommentControl, Control } from "../controls";
return false
}

private sectionRow(doc:Document, section: Section, index: number, comments:Array<Comment>) : TemplateResult {
private sectionRow(doc:Document, section: Section, index: number, comments:Array<Comment>, isSteward: boolean) : TemplateResult {
let commentsHTML
if (this.canSeeComments(doc, section)) {
const canMakeComments = this.canMakeComments(doc, section)
Expand Down Expand Up @@ -430,11 +443,13 @@ import { CommentControl, Control } from "../controls";
.document=${doc}
@selection=${(e:any)=>this.openCommentFromSelection(e.detail)}
@section-changed=${(e:any) => this.updateSection(e.detail, index)}
@delete-section=${(e:any) => this.deleteSection(e.detail, index)}
.section=${section}
.index=${index}
.highlitRange=${this.highlitRange && this.highlitRange.sectionName == section.name ? this.highlitRange: undefined}
.readOnly=${this.readOnly}
.comments=${comments}
.isSteward=${isSteward}
>
</how-section>
${commentsHTML}
Expand All @@ -447,35 +462,51 @@ import { CommentControl, Control } from "../controls";
return;
}
const doc : Document = this._documents.value[this.currentDocumentEh]
const unit: Unit = this._units.value[encodeHashToBase64(doc.unitHash)]
const isSteward = unit.stewards.includes(this._store.myAgentPubKey)

let addSectionHTML
if (doc.canAddSection() && !this.readOnly) {
const document = this._documents.value[this.currentDocumentEh]
addSectionHTML = html`
<svg-button
button="plus"
info="add section"
infoPosition="right"
.click=${() => this._newSectionDialog.open()}
></svg-button>
</div>
<how-new-section-dialog
.takenNames=${doc.content.map((s)=>s.name)}
@add-section=${this.addSection}
sectionType=${SectionType.Content}
></how-new-section-dialog>
${this.availbleCollectionSections.length ? this.availbleCollectionSections.map(type => html`
<svg-button
button="plus"
info="add ${type} collection section"
infoPosition="right"
.click=${() => {
console.log("FISH")
this.dispatchEvent(new CustomEvent('add-section', { detail: {name: type, contentType: "text/markdown", sectionType: SectionType.Content}, bubbles: true, composed: true }))
}}
></svg-button>
</div>
${ this.collectionDefs ?
this.collectionDefs.map((def) => html`
<svg-button
button="plus"
info="add ${def.name} collection section"
infoPosition="right"
.click=${() => {
this.addSection(def)
}}
></svg-button>
</div>`) :
html`Loading...`
}
<svg-button
button="plus"
info="add section"
infoPosition="right"
.click=${() => this._newSectionDialog.open()}
></svg-button>
</div>
`) : ""}
<how-new-section-dialog
.takenNames=${doc.content.map((s)=>s.name)}
@add-section=${(e:any) => {
const section: Section = {
name:e.detail.name,
contentType:e.detail.contentType,
sectionType:e.detail.sectionType,
sourcePath: SourceManual,
content: ""
}
this.addSection(section)
}}
sectionType=${SectionType.Content}
></how-new-section-dialog>
`
}

Expand All @@ -486,10 +517,10 @@ import { CommentControl, Control } from "../controls";
this.controls = doc.controls()

const sectionsHTML = sections.map((section, index) =>
this.sectionRow(doc, section, index, comments[section.name]))
this.sectionRow(doc, section, index, comments[section.name], isSteward))
const requirements = doc.content.filter(section => section.sectionType == SectionType.Requirement)
let requirementsHTML = requirements.map((section, index) =>
this.sectionRow(doc, section, index, comments[section.name]))
this.sectionRow(doc, section, index, comments[section.name], isSteward))
if (requirementsHTML.length > 0) {
requirementsHTML.unshift(html`
<info-item item="Requirements" name="sections that this standard requires of sub-nodes"></info-item>
Expand Down Expand Up @@ -525,11 +556,15 @@ import { CommentControl, Control } from "../controls";
})
return html`
<div id="header">
${tasksHTML.length>0 ? html`<div class="tasks">${tasksHTML}</div>`:''}
${affordancesHTML.length>0 ? html`<div class="affordances">${affordancesHTML}</div>`:''}
<div id="editors" class="row">
Editors: <how-agent-list layout="row" .agents=${doc.editors}></how-agent-list>
</div>
${doc.documentType == DocType.Collection ? html`<h3>Collection</h3>` :
html`
${tasksHTML.length>0 ? html`<div class="tasks">${tasksHTML}</div>`:''}
${affordancesHTML.length>0 ? html`<div class="affordances">${affordancesHTML}</div>`:''}
<div id="editors" class="row">
Editors: <how-agent-list layout="row" .agents=${doc.editors}></how-agent-list>
</div>
`
}
</div>
<div id="sections" >
${sectionsHTML}
Expand Down
1 change: 0 additions & 1 deletion ui/src/elements/how-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {sharedStyles} from "../sharedStyles";
import {Unit, DocType, howContext, Document, DocumentOutput, SysState, Progress, UnitFlags} from "../types";
import {HowStore} from "../how.store";
import {ScopedElementsMixin} from "@open-wc/scoped-elements";
import { StoreSubscriber } from "@holochain-open-dev/stores";
import {unsafeHTML} from "lit/directives/unsafe-html.js";
import { aliveImage, underConstructionImage } from "../images";
const angleInRadians = (angleInDegrees: number) => (angleInDegrees - 90) * (Math.PI / 180.0);
Expand Down
13 changes: 13 additions & 0 deletions ui/src/elements/how-section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export class HowSection extends ScopedElementsMixin(LitElement) {
@property() highlitRange: HilightRange | undefined = undefined;
@property() comments:Array<Comment> = []
@property() document: Document | undefined
@property() isSteward = false

@state() editing = false;
@state() preview = false;
Expand Down Expand Up @@ -252,6 +253,9 @@ export class HowSection extends ScopedElementsMixin(LitElement) {
((this.section.contentType == "text/markdown") ||
(this.comments && this.comments.length>0 && this.comments.find(c=>c.status==CommentStatus.Approved && (c.suggestion() != undefined))))
}
private deletable() {
return this.section && this.isSteward && this.section.sourcePath != "" && !this.readOnly
}
render() {
if (this.section) {
const controls = [html`
Expand Down Expand Up @@ -298,6 +302,15 @@ export class HowSection extends ScopedElementsMixin(LitElement) {
></svg-button>`
)
}
if (this.deletable()) {
controls.push(html`<svg-button
button="trash"
info="delete"
infoPosition="right"
.click=${() => this.dispatchEvent(new CustomEvent('delete-section', { detail: this.section, bubbles: true, composed: true }))}
></svg-button>`)

}
const sectionNameBar = html`
<div class="section-name-bar row">
<div class="section-name">
Expand Down
Loading

0 comments on commit d559b93

Please sign in to comment.