{"action":"created","issue":{"url":"https://api.github.com/repos/substance/texture/issues/543","repository_url":"https://api.github.com/repos/substance/texture","labels_url":"https://api.github.com/repos/substance/texture/issues/543/labels{/name}","comments_url":"https://api.github.com/repos/substance/texture/issues/543/comments","events_url":"https://api.github.com/repos/substance/texture/issues/543/events","html_url":"https://github.com/substance/texture/issues/543","id":327045931,"number":543,"title":"Towards a TextureDocument API","user":{"login":"michael","id":2931,"avatar_url":"https://avatars1.githubusercontent.com/u/2931?v=4","gravatar_id":"","url":"https://api.github.com/users/michael","html_url":"https://github.com/michael","followers_url":"https://api.github.com/users/michael/followers","following_url":"https://api.github.com/users/michael/following{/other_user}","gists_url":"https://api.github.com/users/michael/gists{/gist_id}","starred_url":"https://api.github.com/users/michael/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michael/subscriptions","organizations_url":"https://api.github.com/users/michael/orgs","repos_url":"https://api.github.com/users/michael/repos","events_url":"https://api.github.com/users/michael/events{/privacy}","received_events_url":"https://api.github.com/users/michael/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2018-05-28T14:32:22Z","updated_at":"2018-05-28T14:59:10Z","closed_at":null,"author_association":"MEMBER","body":"I'm working on the reader and creating new components while trying to design them reusable (for editor and reader) and less dependent on the internal Texture XML model.\r\n\r\nI've found that we work directly with the XML model a lot. Also we named our components after the XML elements. E.g. FrontComponent, BodyComponent etc., maybe we should question that.\r\n\r\nI'd like to move towards a range of independent components that depend on a slim API for accessing content, instead of working with the XML tree directly.\r\n\r\nSo far we did it like this:\r\n\r\n```js\r\n    el.append(\r\n      $$(ArticleHeaderComponent, {\r\n        node: frontNode\r\n      }).ref('articleHeader'),\r\n      $$('div').addClass('main-content').append(\r\n        $$(ArticleAbstractComponent, {\r\n          node: abstractNode\r\n        }).ref('articleAbstract'),\r\n        $$(ArticleBodyComponent, {\r\n          node: bodyNode\r\n        }).ref('articleBody'),\r\n        $$(ArticleReferencesComponent, {\r\n          node: refListNode\r\n        }).ref('articleReferences')\r\n      )\r\n    )\r\n```\r\n\r\nAnd in the ArticleAbstractComponent:\r\n\r\n```js\r\n      el.append(\r\n        $$('h1').addClass('sc-heading').append('Abstract')\r\n      )\r\n      // There can be multiple abstracts. We just take the first\r\n      const content = node.findChild('abstract-content')\r\n      let contentEl\r\n      if (content) {\r\n        contentEl = $$(this.getComponent('container'), {\r\n          placeholder: 'Enter Abstract',\r\n          name: 'abstractEditor',\r\n          node: content,\r\n          disabled: this.props.disabled\r\n        })\r\n      } else {\r\n        // TODO: ability to add an abstract\r\n      }\r\n      el.append(contentEl)\r\n```\r\n\r\n--- \r\n\r\n\r\nHere's a rough proposal of introducing API objects that hide the details of the xml implementation behind the scenes. \r\n\r\n```js\r\n    const api = this.editorSession.getAPI()\r\n\r\n    el.append(\r\n      $$(ArticleHeaderComponent, {\r\n        title: api.getArticleTitle(),\r\n        authors: api.getAuthors(),\r\n      }).ref('articleHeader'),\r\n      $$('div').addClass('main-content').append(\r\n        $$(ArticleAbstractComponent, {\r\n          model: api.getAbstract()\r\n        }).ref('articleHeader'),\r\n        $$(ArticleBodyComponent, {\r\n          model: api.getBody()\r\n        }).ref('articleBody'),\r\n        $$(ArticleReferencesComponent, {\r\n          model: api.getReferences()\r\n        }).ref('articleReferences')\r\n      )\r\n    )\r\n```\r\n\r\nThen we could remove things like node.find from ArticleAbstractComponent and instead use an AbstractModel API.\r\n\r\n```js\r\n  render($$) {\r\n    const abstract = this.props.model\r\n    \r\n    let el = $$('div')\r\n      .addClass('sc-abstract')\r\n      .attr('data-id', abstract.id)\r\n\r\n    el.append(\r\n      $$('h1').addClass('sc-heading').append('Abstract')\r\n    )\r\n\r\n    let contentEl = $$(this.getComponent('container'), {\r\n      placeholder: 'Enter Abstract',\r\n      name: 'abstractEditor',\r\n      node: abstract.getContainer(),\r\n      disabled: this.props.disabled\r\n    })\r\n    el.append(contentEl)\r\n\r\n    return el\r\n  }\r\n```\r\n\r\nthis.props.model would be of type AbstractModel and provide the minimal API to serve components to read and write information as needed.\r\n\r\n```js\r\nabstract.getContainer() // returns an XMLContainerNode (interface for ContainerEditor)\r\nabstract.getText() // get Abstract as plain text\r\nabstract.empty() // clear abstract\r\n```\r\n\r\nFor references we can provide a dedicated API too, that behind the scences writes into the XML + entity db.\r\n\r\n```js\r\nlet references = api.getReferences()\r\n\r\nreferences.addReference({...})\r\nreferences.deleteReference({...})\r\nreferences.forEach() // iterate over sorted reference list\r\n```\r\n\r\n```js\r\nlet figure = api.getFigure('fig1')\r\n\r\nfigure.setTitle('Bla blup') // ability to programmatically set the title (xPub etc. may use this)\r\nfigure.getLabel() // get the automatically generated label\r\n...\r\n```\r\n\r\n@oliver---- is this a good idea, or is it rather overkill that adds another layer that a developer needs to understand? If we do it, I guess we should really always go through an API call and never use low-level xml manipulation"},"comment":{"url":"https://api.github.com/repos/substance/texture/issues/comments/392548740","html_url":"https://github.com/substance/texture/issues/543#issuecomment-392548740","issue_url":"https://api.github.com/repos/substance/texture/issues/543","id":392548740,"user":{"login":"michael","id":2931,"avatar_url":"https://avatars1.githubusercontent.com/u/2931?v=4","gravatar_id":"","url":"https://api.github.com/users/michael","html_url":"https://github.com/michael","followers_url":"https://api.github.com/users/michael/followers","following_url":"https://api.github.com/users/michael/following{/other_user}","gists_url":"https://api.github.com/users/michael/gists{/gist_id}","starred_url":"https://api.github.com/users/michael/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/michael/subscriptions","organizations_url":"https://api.github.com/users/michael/orgs","repos_url":"https://api.github.com/users/michael/repos","events_url":"https://api.github.com/users/michael/events{/privacy}","received_events_url":"https://api.github.com/users/michael/received_events","type":"User","site_admin":false},"created_at":"2018-05-28T14:59:10Z","updated_at":"2018-05-28T14:59:10Z","author_association":"MEMBER","body":"> Nevertheless, with your proposed solution you will find yourself with no updates anymore.\r\nYou need to do something similar as NodeComponent.\r\n\r\nTrue, but this could then be a chance to model the updates better. E.g. sometimes we have different elements (abstract+abstract-content) we need to listen to but they form one semantic unit, so this could be a chance to group them together again, and just say, when the model updates, rerender the component."}}
{"actor":{"display_login":"michael"}}