diff --git a/app/app/components/section/wysiwyg/type-editor.js b/app/app/components/section/wysiwyg/type-editor.js
index 2ad5e6b7..c8219199 100644
--- a/app/app/components/section/wysiwyg/type-editor.js
+++ b/app/app/components/section/wysiwyg/type-editor.js
@@ -115,7 +115,3 @@ export default Ember.Component.extend({
}
}
});
-
-// editor.insertContent(' It\'s my button! ');
-// Selects the first paragraph found
-// tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select('p')[0]);
diff --git a/app/app/services/link.js b/app/app/services/link.js
index 4c5a2790..224d7838 100644
--- a/app/app/services/link.js
+++ b/app/app/services/link.js
@@ -39,34 +39,41 @@ export default Ember.Service.extend({
href = `/link/${link.linkType}/${link.id}`;
}
if (link.linkType === "file") {
- href = `${endpoint}/public/attachments/${orgId}/${link.attachmentId}`;
+ href = `${endpoint}/public/attachments/${orgId}/${link.targetId}`;
}
if (link.linkType === "document") {
href = `/link/${link.linkType}/${link.id}`;
}
- result = `${link.title}`;
+ result = `${link.title}`;
- console.log(link);
- console.log(result);
return result;
}
});
/*
+link handler
+ - implement link redirect handler --
+ - for documents: client-side detect
+ - for sections:
+ - for attachments: direct link
+ -
+
+onDelete document/section/file:
+ - mark link table row as ORPHAN
+ - doc view: meta data fetch to load orphaned content
+
+Keyword search results - docs, section, files
+
we should not redirect to a link that is in the same document!
-
what happens if we delete attachment?
-
UpdatePage(): find and persist links from saved content
-
-
-
1. We need to deal with links server-side
2. We need to click on links in the browser and 'navigate' to linked content
-
-
+editor.insertContent(' It\'s my button! ');
+Selects the first paragraph found
+tinyMCE.activeEditor.selection.select(tinyMCE.activeEditor.dom.select('p')[0]);
*/
diff --git a/app/app/styles/view/document/edit-tools.scss b/app/app/styles/view/document/edit-tools.scss
index 59e78607..14ecdd56 100644
--- a/app/app/styles/view/document/edit-tools.scss
+++ b/app/app/styles/view/document/edit-tools.scss
@@ -14,7 +14,7 @@
.link-item {
margin: 0;
- padding: 5px 0;
+ padding: 2px 0;
font-size: 0.9rem;
color: $color-gray;
cursor: pointer;
diff --git a/app/app/templates/components/document/edit-tools.hbs b/app/app/templates/components/document/edit-tools.hbs
index 890ef044..068f0885 100644
--- a/app/app/templates/components/document/edit-tools.hbs
+++ b/app/app/templates/components/document/edit-tools.hbs
@@ -28,7 +28,7 @@
{{#each candidates.attachments as |a|}}
{{#ui/ui-checkbox selected=a.selected}}
-
+
{{ a.title }}
{{/ui/ui-checkbox}}
diff --git a/core/api/endpoint/link_endpoint.go b/core/api/endpoint/link_endpoint.go
index 1472ffa9..74e83436 100644
--- a/core/api/endpoint/link_endpoint.go
+++ b/core/api/endpoint/link_endpoint.go
@@ -69,7 +69,7 @@ func GetLinkCandidates(w http.ResponseWriter, r *http.Request) {
c := entity.LinkCandidate{
RefID: util.UniqueID(),
DocumentID: documentID,
- PageID: p.RefID,
+ TargetID: p.RefID,
LinkType: "section",
Title: p.Title,
}
@@ -94,12 +94,12 @@ func GetLinkCandidates(w http.ResponseWriter, r *http.Request) {
for _, f := range files {
c := entity.LinkCandidate{
- RefID: util.UniqueID(),
- DocumentID: documentID,
- AttachmentID: f.RefID,
- LinkType: "file",
- Title: f.Filename,
- AttachmentExtension: f.Extension,
+ RefID: util.UniqueID(),
+ DocumentID: documentID,
+ TargetID: f.RefID,
+ LinkType: "file",
+ Title: f.Filename,
+ Context: f.Extension,
}
fc = append(fc, c)
diff --git a/core/api/entity/objects.go b/core/api/entity/objects.go
index 7c00bdd7..d99d273a 100644
--- a/core/api/entity/objects.go
+++ b/core/api/entity/objects.go
@@ -346,25 +346,21 @@ type SitemapDocument struct {
// Link defines a reference between a section and another document/section/attachment.
type Link struct {
BaseEntity
- OrgID string `json:"orgId"`
- UserID string `json:"userId"`
- LinkType string `json:"linkType"`
- SourceID string `json:"sourceId"`
- DocumentID string `json:"documentId"`
- PageID string `json:"pageId"`
- AttachmentID string `json:"attachmentId"`
- Orphan bool `json:"orphan"`
+ OrgID string `json:"orgId"`
+ UserID string `json:"userId"`
+ LinkType string `json:"linkType"`
+ SourceID string `json:"sourceId"`
+ DocumentID string `json:"documentId"`
+ TargetID string `json:"targetId"`
+ Orphan bool `json:"orphan"`
}
// LinkCandidate defines a potential link to a document/section/attachment.
type LinkCandidate struct {
- RefID string `json:"id"`
- OrgID string `json:"orgId"`
- LinkType string `json:"linkType"`
- DocumentID string `json:"documentId"`
- PageID string `json:"pageId"`
- AttachmentID string `json:"attachmentId"`
- AttachmentExtension string `json:"attachmentExtension"`
- Title string `json:"title"` // what we label the link
- Context string `json:"context"` // additional context (e.g. excerpt, parent)
+ RefID string `json:"id"`
+ LinkType string `json:"linkType"`
+ DocumentID string `json:"documentId"`
+ TargetID string `json:"targetId"`
+ Title string `json:"title"` // what we label the link
+ Context string `json:"context"` // additional context (e.g. excerpt, parent, file extension)
}
diff --git a/core/api/request/link.go b/core/api/request/link.go
index 0f829aea..2e20ba93 100644
--- a/core/api/request/link.go
+++ b/core/api/request/link.go
@@ -20,14 +20,14 @@ import (
"github.com/documize/community/core/utility"
)
-// AddLink inserts wiki-link into the store.
+// AddContentLink inserts wiki-link into the store.
// These links exist when content references another document or content.
-func (p *Persister) AddLink(l entity.Link) (err error) {
+func (p *Persister) AddContentLink(l entity.Link) (err error) {
l.UserID = p.Context.UserID
l.Created = time.Now().UTC()
l.Revised = time.Now().UTC()
- stmt, err := p.Context.Transaction.Preparex("INSERT INTO link (refid, orgid, userid, sourceid, documentid, pageid, linktype, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
+ stmt, err := p.Context.Transaction.Preparex("INSERT INTO link (refid, orgid, userid, sourceid, documentid, targetid, linktype, created, revised) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)")
defer utility.Close(stmt)
if err != nil {
@@ -35,7 +35,7 @@ func (p *Persister) AddLink(l entity.Link) (err error) {
return
}
- _, err = stmt.Exec(l.RefID, l.OrgID, l.UserID, l.SourceID, l.DocumentID, l.PageID, l.LinkType, l.Created, l.Revised)
+ _, err = stmt.Exec(l.RefID, l.OrgID, l.UserID, l.SourceID, l.DocumentID, l.TargetID, l.LinkType, l.Created, l.Revised)
if err != nil {
log.Error("Unable to execute insert for link", err)
@@ -49,7 +49,7 @@ func (p *Persister) AddLink(l entity.Link) (err error) {
func (p *Persister) GetReferencedLinks(sectionID string) (links []entity.Link, err error) {
err = nil
- sql := "SELECT id,refid,orgid,userid,sourceid,documentid,sectionid,linktype,orphan,created,revised from link WHERE orgid=? AND sourceid=?"
+ sql := "SELECT id,refid,orgid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND sourceid=?"
err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
@@ -61,11 +61,11 @@ func (p *Persister) GetReferencedLinks(sectionID string) (links []entity.Link, e
return
}
-// GetLinksToSection returns all links that are linking to the specified section.
-func (p *Persister) GetLinksToSection(sectionID string) (links []entity.Link, err error) {
+// GetContentLinksForSection returns all links that are linking to the specified section.
+func (p *Persister) GetContentLinksForSection(sectionID string) (links []entity.Link, err error) {
err = nil
- sql := "SELECT id,refid,orgid,userid,sourceid,documentid,sectionid,linktype,orphan,created,revised from link WHERE orgid=? AND sectionid=?"
+ sql := "SELECT id,refid,orgid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND sectionid=?"
err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
@@ -77,11 +77,11 @@ func (p *Persister) GetLinksToSection(sectionID string) (links []entity.Link, er
return
}
-// GetLinksToDocument returns all links that are linking to the specified document.
-func (p *Persister) GetLinksToDocument(documentID string) (links []entity.Link, err error) {
+// GetContentLinksForDocument returns all links that are linking to the specified document.
+func (p *Persister) GetContentLinksForDocument(documentID string) (links []entity.Link, err error) {
err = nil
- sql := "SELECT id,refid,orgid,userid,sourceid,documentid,sectionid,linktype,orphan,created,revised from link WHERE orgid=? AND documentid=?"
+ sql := "SELECT id,refid,orgid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND documentid=?"
err = Db.Select(&links, sql, p.Context.OrgID, documentID)
@@ -93,8 +93,8 @@ func (p *Persister) GetLinksToDocument(documentID string) (links []entity.Link,
return
}
-// MarkLinkAsOrphan marks the link record as being invalid.
-func (p *Persister) MarkLinkAsOrphan(l entity.Link) (err error) {
+// MarkOrphanContentLink marks the link record as being invalid.
+func (p *Persister) MarkOrphanContentLink(l entity.Link) (err error) {
l.Orphan = true
l.Revised = time.Now().UTC()
@@ -116,50 +116,12 @@ func (p *Persister) MarkLinkAsOrphan(l entity.Link) (err error) {
return
}
+// DeleteSourceLinks removes saved links for given source.
+func (p *Persister) DeleteSourceLinks(sourceID string) (rows int64, err error) {
+ return p.Base.DeleteWhere(p.Context.Transaction, fmt.Sprintf("DELETE FROM link WHERE orgid=\"%s\" AND sourceid=\"%s\"", p.Context.OrgID, sourceID))
+}
+
// DeleteLink removes saved link from the store.
func (p *Persister) DeleteLink(id string) (rows int64, err error) {
return p.Base.DeleteConstrained(p.Context.Transaction, "link", p.Context.OrgID, id)
}
-
-// GetLinkCandidates returns matching results based upon specified parameters.
-// func (p *Persister) GetLinkCandidates(keywords string) (c []entity.LinkCandidate, err error) {
-// err = nil
-//
-// sql := "SELECT id,refid,orgid,userid,sourceid,documentid,sectionid,linktype,orphan,created,revised from link WHERE orgid=? AND sectionid=?"
-//
-// err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
-//
-// if err != nil {
-// log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
-// return
-// }
-//
-// return
-// }
-//
-// package main
-//
-// import (
-// "fmt"
-// "regexp"
-// )
-//
-// var imgRE = regexp.MustCompile(`]+\bhref=["']([^"']+)["']`)
-//
-// func findImages(htm string) []string {
-// imgs := imgRE.FindAllStringSubmatch(htm, -1)
-// out := make([]string, len(imgs))
-// for i := range out {
-// out[i] = imgs[i][1]
-// }
-// return out
-// }
-//
-// func main() {
-// fmt.Printf("%q", findImages(data))
-// }
-//
-// const data = `
-// dfdfdf
-//
-// `
diff --git a/core/api/request/page.go b/core/api/request/page.go
index a8c869be..ece2c741 100644
--- a/core/api/request/page.go
+++ b/core/api/request/page.go
@@ -20,6 +20,7 @@ import (
"github.com/documize/community/core/api/endpoint/models"
"github.com/documize/community/core/api/entity"
+ "github.com/documize/community/core/api/util"
"github.com/documize/community/core/log"
"github.com/documize/community/core/utility"
)
@@ -286,6 +287,27 @@ func (p *Persister) UpdatePage(page entity.Page, refID, userID string, skipRevis
//}
//}
+ // fimnd any content links
+ links := util.GetContentLinks(page.Body)
+
+ // delete previous content links for this page
+ _, _ = p.DeleteSourceLinks(page.RefID)
+
+ // save latest content links for this page
+ for _, link := range links {
+ link.OrgID = p.Context.OrgID
+ link.UserID = p.Context.UserID
+ link.SourceID = page.RefID
+ link.Orphan = false
+
+ err := p.AddContentLink(link)
+
+ if err != nil {
+ log.Error(fmt.Sprintf("Unable to insert content links for page %s", page.RefID), err)
+ return err
+ }
+ }
+
p.Base.Audit(p.Context, "update-page", page.DocumentID, page.RefID)
return
diff --git a/core/api/util/links.go b/core/api/util/links.go
new file mode 100644
index 00000000..afa8ddb4
--- /dev/null
+++ b/core/api/util/links.go
@@ -0,0 +1,73 @@
+// Copyright 2016 Documize Inc. . All rights reserved.
+//
+// This software (Documize Community Edition) is licensed under
+// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
+//
+// You can operate outside the AGPL restrictions by purchasing
+// Documize Enterprise Edition and obtaining a commercial license
+// by contacting .
+//
+// https://documize.com
+
+package util
+
+import (
+ "strings"
+
+ "golang.org/x/net/html"
+
+ "github.com/documize/community/core/api/entity"
+)
+
+// GetContentLinks returns Documize generated links.
+// such links have an identifying attribute e.g. tag
+ isAnchor := t.Data == "a"
+ if !isAnchor {
+ continue
+ }
+
+ // Extract the content link
+ ok, link := getLink(t)
+ if ok {
+ links = append(links, link)
+ }
+ }
+ }
+}
+
+// Helper function to pull the href attribute from a Token
+func getLink(t html.Token) (ok bool, link entity.Link) {
+ ok = false
+
+ // Iterate over all of the Token's attributes until we find an "href"
+ for _, a := range t.Attr {
+ switch a.Key {
+ case "data-documize":
+ ok = true
+ case "data-link-id":
+ link.RefID = strings.TrimSpace(a.Val)
+ case "data-link-document-id":
+ link.DocumentID = strings.TrimSpace(a.Val)
+ case "data-link-target-id":
+ link.TargetID = strings.TrimSpace(a.Val)
+ case "data-link-type":
+ link.LinkType = strings.TrimSpace(a.Val)
+ }
+ }
+
+ return
+}
diff --git a/core/database/scripts/autobuild/db_00000.sql b/core/database/scripts/autobuild/db_00000.sql
index 0b92e6dc..79098323 100644
--- a/core/database/scripts/autobuild/db_00000.sql
+++ b/core/database/scripts/autobuild/db_00000.sql
@@ -319,14 +319,14 @@ CREATE TABLE IF NOT EXISTS `link` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`refid` CHAR(16) NOT NULL COLLATE utf8_bin,
`orgid` CHAR(16) NOT NULL COLLATE utf8_bin,
- `sourceid` CHAR(16) NOT NULL COLLATE utf8_bin,
- `documentid` CHAR(16) NOT NULL COLLATE utf8_bin,
- `sectionid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
`userid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
+ `sourceid` CHAR(16) NOT NULL COLLATE utf8_bin,
`linktype` CHAR(16) NOT NULL COLLATE utf8_bin,
+ `documentid` CHAR(16) NOT NULL COLLATE utf8_bin,
+ `targetid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
`orphan` BOOL NOT NULL DEFAULT 0,
`created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ `revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT pk_id PRIMARY KEY (id))
DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci
ENGINE = InnoDB;
diff --git a/core/database/scripts/autobuild/db_00004.sql b/core/database/scripts/autobuild/db_00004.sql
index 1dc15b0d..3872dc4b 100644
--- a/core/database/scripts/autobuild/db_00004.sql
+++ b/core/database/scripts/autobuild/db_00004.sql
@@ -5,11 +5,11 @@ CREATE TABLE IF NOT EXISTS `link` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`refid` CHAR(16) NOT NULL COLLATE utf8_bin,
`orgid` CHAR(16) NOT NULL COLLATE utf8_bin,
- `sourceid` CHAR(16) NOT NULL COLLATE utf8_bin,
- `documentid` CHAR(16) NOT NULL COLLATE utf8_bin,
- `sectionid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
`userid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
+ `sourceid` CHAR(16) NOT NULL COLLATE utf8_bin,
`linktype` CHAR(16) NOT NULL COLLATE utf8_bin,
+ `documentid` CHAR(16) NOT NULL COLLATE utf8_bin,
+ `targetid` CHAR(16) DEFAULT '' COLLATE utf8_bin,
`orphan` BOOL NOT NULL DEFAULT 0,
`created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`revised` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,