mirror of
https://github.com/documize/community.git
synced 2025-07-20 13:49:42 +02:00
search results for links
This commit is contained in:
parent
899b4f978c
commit
ad716a23ba
12 changed files with 390 additions and 69 deletions
|
@ -21,6 +21,11 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
linkName: '',
|
linkName: '',
|
||||||
keywords: '',
|
keywords: '',
|
||||||
selection: null,
|
selection: null,
|
||||||
|
matches: {
|
||||||
|
documents: [],
|
||||||
|
pages: [],
|
||||||
|
attachments: []
|
||||||
|
},
|
||||||
tabs: [
|
tabs: [
|
||||||
{ label: 'Section', selected: true },
|
{ label: 'Section', selected: true },
|
||||||
{ label: 'Attachment', selected: false },
|
{ label: 'Attachment', selected: false },
|
||||||
|
@ -36,6 +41,11 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
showSearch: Ember.computed('tabs.@each.selected', function() {
|
showSearch: Ember.computed('tabs.@each.selected', function() {
|
||||||
return this.get('tabs').findBy('label', 'Search').selected;
|
return this.get('tabs').findBy('label', 'Search').selected;
|
||||||
}),
|
}),
|
||||||
|
hasMatches: Ember.computed('matches', function() {
|
||||||
|
let m = this.get('matches');
|
||||||
|
return m.documents.length || m.pages.length || m.attachments.length;
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
@ -60,11 +70,30 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
this.destroyTooltips();
|
this.destroyTooltips();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onKeywordChange: function () {
|
||||||
|
Ember.run.debounce(this, this.fetch, 750);
|
||||||
|
}.observes('keywords'),
|
||||||
|
|
||||||
|
fetch() {
|
||||||
|
let keywords = this.get('keywords');
|
||||||
|
let self = this;
|
||||||
|
|
||||||
|
if (_.isEmpty(keywords)) {
|
||||||
|
this.set('matches', { documents: [], pages: [], attachments: [] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.get('link').searchCandidates(keywords).then(function (matches) {
|
||||||
|
self.set('matches', matches);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
setSelection(i) {
|
setSelection(i) {
|
||||||
this.set('selection', i);
|
|
||||||
|
|
||||||
let candidates = this.get('candidates');
|
let candidates = this.get('candidates');
|
||||||
|
let matches = this.get('matches');
|
||||||
|
|
||||||
|
this.set('selection', i);
|
||||||
|
|
||||||
candidates.pages.forEach(c => {
|
candidates.pages.forEach(c => {
|
||||||
Ember.set(c, 'selected', c.id === i.id);
|
Ember.set(c, 'selected', c.id === i.id);
|
||||||
|
@ -73,6 +102,18 @@ export default Ember.Component.extend(TooltipMixin, {
|
||||||
candidates.attachments.forEach(c => {
|
candidates.attachments.forEach(c => {
|
||||||
Ember.set(c, 'selected', c.id === i.id);
|
Ember.set(c, 'selected', c.id === i.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
matches.documents.forEach(c => {
|
||||||
|
Ember.set(c, 'selected', c.id === i.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
matches.pages.forEach(c => {
|
||||||
|
Ember.set(c, 'selected', c.id === i.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
matches.attachments.forEach(c => {
|
||||||
|
Ember.set(c, 'selected', c.id === i.id);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
onInsertLink() {
|
onInsertLink() {
|
||||||
|
|
15
app/app/components/ui/ui-selection.js
Normal file
15
app/app/components/ui/ui-selection.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2016 Documize Inc. <legal@documize.com>. 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 <sales@documize.com>.
|
||||||
|
//
|
||||||
|
// https://documize.com
|
||||||
|
|
||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
});
|
|
@ -22,7 +22,7 @@ export default Ember.Service.extend({
|
||||||
store: service(),
|
store: service(),
|
||||||
|
|
||||||
// Returns candidate links using provided parameters
|
// Returns candidate links using provided parameters
|
||||||
getCandidates(folderId, documentId, pageId /*, keywords*/ ) {
|
getCandidates(folderId, documentId, pageId) {
|
||||||
return this.get('ajax').request(`links/${folderId}/${documentId}/${pageId}`, {
|
return this.get('ajax').request(`links/${folderId}/${documentId}/${pageId}`, {
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
|
@ -30,6 +30,27 @@ export default Ember.Service.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Returns keyword-based candidates
|
||||||
|
searchCandidates(keywords) {
|
||||||
|
let url = "links?keywords=" + encodeURIComponent(keywords);
|
||||||
|
|
||||||
|
return this.get('ajax').request(url, {
|
||||||
|
method: 'GET'
|
||||||
|
}).then((response) => {
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// getUsers returns all users for organization.
|
||||||
|
find(keywords) {
|
||||||
|
let url = "search?keywords=" + encodeURIComponent(keywords);
|
||||||
|
|
||||||
|
return this.get('ajax').request(url, {
|
||||||
|
method: "GET"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
buildLink(link) {
|
buildLink(link) {
|
||||||
let result = "";
|
let result = "";
|
||||||
let href = "";
|
let href = "";
|
||||||
|
@ -45,7 +66,6 @@ export default Ember.Service.extend({
|
||||||
result = `<a data-documize='true' data-link-space-id='${link.folderId}' data-link-id='${link.id}' data-link-document-id='${link.documentId}' data-link-target-id='${link.targetId}' data-link-type='${link.linkType}' href='${href}'>${link.title}</a>`;
|
result = `<a data-documize='true' data-link-space-id='${link.folderId}' data-link-id='${link.id}' data-link-document-id='${link.documentId}' data-link-target-id='${link.targetId}' data-link-type='${link.linkType}' href='${href}'>${link.title}</a>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -85,7 +105,7 @@ export default Ember.Service.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle document link
|
// handle document link
|
||||||
if (link.inkType === "document") {
|
if (link.linkType === "document") {
|
||||||
router.transitionTo('document', link.folderId, folderSlug, link.documentId, documentSlug);
|
router.transitionTo('document', link.folderId, folderSlug, link.documentId, documentSlug);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +119,6 @@ export default Ember.Service.extend({
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Keyword search results - docs, section, files
|
|
||||||
|
|
||||||
The link id's get ZERO'd in Page.Body whenever:
|
The link id's get ZERO'd in Page.Body whenever:
|
||||||
- doc is moved to different space
|
- doc is moved to different space
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
.edit-tools {
|
.edit-tools {
|
||||||
margin: 0 0 0 20px;
|
margin: 0 0 0 20px;
|
||||||
min-height: 500px;
|
min-height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-linker-dialog {
|
.content-linker-dialog {
|
||||||
width: 350px;
|
width: 350px;
|
||||||
height: 400px;
|
height: 500px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.link-list {
|
.link-list {
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
.link-item {
|
.link-item {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px 0;
|
padding: 0;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
color: $color-gray;
|
color: $color-gray;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
34
app/app/styles/widget/widget-selection.scss
Normal file
34
app/app/styles/widget/widget-selection.scss
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
.widget-selection {
|
||||||
|
> .option {
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px 10px;
|
||||||
|
text-align: left;
|
||||||
|
@extend .no-select;
|
||||||
|
cursor: pointer;
|
||||||
|
// border: 1px solid $color-border;
|
||||||
|
color: $color-off-black;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
> i.material-icons {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@include ease-in();
|
||||||
|
background-color: $color-off-white;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .selected {
|
||||||
|
background-color: $color-card-active !important;
|
||||||
|
color: $color-primary !important;
|
||||||
|
|
||||||
|
> i.material-icons {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,27 +1,29 @@
|
||||||
.widget-tab {
|
.widget-tab {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 5px;
|
padding: 0 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-bottom: 1px solid $color-border;
|
@extend .no-select;
|
||||||
|
|
||||||
> .tab {
|
> .tab {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
color: $color-off-black;
|
background-color: $color-off-white;
|
||||||
|
color: $color-gray;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@include ease-in();
|
margin-right: -3px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $color-off-white;
|
@include ease-in();
|
||||||
color: $color-link;
|
background-color: $color-gray;
|
||||||
|
color: $color-off-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .selected {
|
> .selected {
|
||||||
background-color: $color-off-white;
|
background-color: $color-gray;
|
||||||
color: $color-link;
|
color: $color-off-white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
.z-depth-5 {
|
.z-depth-5 {
|
||||||
box-shadow: 0 27px 24px 0 rgba(0, 0, 0, 0.2), 0 40px 77px 0 rgba(0, 0, 0, 0.22);
|
box-shadow: 0 27px 24px 0 rgba(0, 0, 0, 0.2), 0 40px 77px 0 rgba(0, 0, 0, 0.22);
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "widget-avatar";
|
@import "widget-avatar";
|
||||||
@import "widget-button";
|
@import "widget-button";
|
||||||
@import "widget-card";
|
@import "widget-card";
|
||||||
|
@ -72,3 +73,4 @@
|
||||||
@import "widget-tooltip";
|
@import "widget-tooltip";
|
||||||
@import "widget-checkbox";
|
@import "widget-checkbox";
|
||||||
@import "widget-tab";
|
@import "widget-tab";
|
||||||
|
@import "widget-selection";
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
<ul class="link-list">
|
<ul class="link-list">
|
||||||
{{#each candidates.pages as |p|}}
|
{{#each candidates.pages as |p|}}
|
||||||
<li class="link-item" {{ action 'setSelection' p }}>
|
<li class="link-item" {{ action 'setSelection' p }}>
|
||||||
{{#ui/ui-checkbox selected=p.selected}}
|
{{#ui/ui-selection selected=p.selected}}
|
||||||
{{p.title}}
|
{{p.title}}
|
||||||
{{/ui/ui-checkbox}}
|
{{/ui/ui-selection}}
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -27,10 +27,10 @@
|
||||||
<ul class="link-list">
|
<ul class="link-list">
|
||||||
{{#each candidates.attachments as |a|}}
|
{{#each candidates.attachments as |a|}}
|
||||||
<li class="link-item" {{ action 'setSelection' a }}>
|
<li class="link-item" {{ action 'setSelection' a }}>
|
||||||
{{#ui/ui-checkbox selected=a.selected}}
|
{{#ui/ui-selection selected=a.selected}}
|
||||||
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
||||||
{{ a.title }}
|
{{ a.title }}
|
||||||
{{/ui/ui-checkbox}}
|
{{/ui/ui-selection}}
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -39,9 +39,36 @@
|
||||||
{{#if showSearch}}
|
{{#if showSearch}}
|
||||||
<div class="input-control">
|
<div class="input-control">
|
||||||
<label>Search</label>
|
<label>Search</label>
|
||||||
<div class="tip">keywords</div>
|
<div class="tip">For content or attachments</div>
|
||||||
{{focus-input id="content-linker-search" type="input" value=keywords placeholder="keyword search"}}
|
{{focus-input id="content-linker-search" type="input" value=keywords placeholder="keyword search"}}
|
||||||
</div>
|
</div>
|
||||||
|
{{#unless hasMatches}}
|
||||||
|
Nothing found.
|
||||||
|
{{/unless}}
|
||||||
|
<ul class="link-list">
|
||||||
|
{{#each matches.documents as |m|}}
|
||||||
|
<li class="link-item" {{ action 'setSelection' m }}>
|
||||||
|
{{#ui/ui-selection selected=m.selected}}
|
||||||
|
{{m.title}}
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
{{#each matches.pages as |m|}}
|
||||||
|
<li class="link-item" {{ action 'setSelection' m }}>
|
||||||
|
{{#ui/ui-selection selected=m.selected}}
|
||||||
|
{{m.title}}<br/><span class="color-gray">{{m.context}}</span>
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
{{#each matches.attachments as |a|}}
|
||||||
|
<li class="link-item" {{ action 'setSelection' a }}>
|
||||||
|
{{#ui/ui-selection selected=a.selected}}
|
||||||
|
<img class="icon" src="/assets/img/attachments/{{document/file-icon a.context}}" />
|
||||||
|
{{ a.title }}
|
||||||
|
{{/ui/ui-selection}}
|
||||||
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="hide regular-button button-blue pull-right" {{ action 'onInsertLink' }}>Insert</div>
|
<div class="hide regular-button button-blue pull-right" {{ action 'onInsertLink' }}>Insert</div>
|
||||||
|
|
6
app/app/templates/components/ui/ui-selection.hbs
Normal file
6
app/app/templates/components/ui/ui-selection.hbs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<div class="widget-selection">
|
||||||
|
<div class="option {{if selected 'selected'}}">
|
||||||
|
{{yield}}
|
||||||
|
<i class="material-icons">check</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -15,12 +15,14 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
"github.com/documize/community/core/api/entity"
|
"github.com/documize/community/core/api/entity"
|
||||||
"github.com/documize/community/core/api/request"
|
"github.com/documize/community/core/api/request"
|
||||||
"github.com/documize/community/core/api/util"
|
"github.com/documize/community/core/api/util"
|
||||||
|
"github.com/documize/community/core/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetLinkCandidates returns references to documents/sections/attachments.
|
// GetLinkCandidates returns references to documents/sections/attachments.
|
||||||
|
@ -112,7 +114,6 @@ func GetLinkCandidates(w http.ResponseWriter, r *http.Request) {
|
||||||
var payload struct {
|
var payload struct {
|
||||||
Pages []entity.LinkCandidate `json:"pages"`
|
Pages []entity.LinkCandidate `json:"pages"`
|
||||||
Attachments []entity.LinkCandidate `json:"attachments"`
|
Attachments []entity.LinkCandidate `json:"attachments"`
|
||||||
Matches []entity.LinkCandidate `json:"matches"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.Pages = pc
|
payload.Pages = pc
|
||||||
|
@ -127,3 +128,40 @@ func GetLinkCandidates(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
util.WriteSuccessBytes(w, json)
|
util.WriteSuccessBytes(w, json)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchLinkCandidates endpoint takes a list of keywords and returns a list of document references matching those keywords.
|
||||||
|
func SearchLinkCandidates(w http.ResponseWriter, r *http.Request) {
|
||||||
|
method := "SearchLinkCandidates"
|
||||||
|
p := request.GetPersister(r)
|
||||||
|
|
||||||
|
query := r.URL.Query()
|
||||||
|
keywords := query.Get("keywords")
|
||||||
|
decoded, err := url.QueryUnescape(keywords)
|
||||||
|
log.IfErr(err)
|
||||||
|
|
||||||
|
docs, pages, attachments, err := p.SearchLinkCandidates(decoded)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
util.WriteServerError(w, method, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload struct {
|
||||||
|
Documents []entity.LinkCandidate `json:"documents"`
|
||||||
|
Pages []entity.LinkCandidate `json:"pages"`
|
||||||
|
Attachments []entity.LinkCandidate `json:"attachments"`
|
||||||
|
}
|
||||||
|
|
||||||
|
payload.Documents = docs
|
||||||
|
payload.Pages = pages
|
||||||
|
payload.Attachments = attachments
|
||||||
|
|
||||||
|
json, err := json.Marshal(payload)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
util.WriteMarshalError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
util.WriteSuccessBytes(w, json)
|
||||||
|
}
|
||||||
|
|
|
@ -214,6 +214,7 @@ func init() {
|
||||||
|
|
||||||
// Links
|
// Links
|
||||||
log.IfErr(Add(RoutePrefixPrivate, "links/{folderID}/{documentID}/{pageID}", []string{"GET", "OPTIONS"}, nil, GetLinkCandidates))
|
log.IfErr(Add(RoutePrefixPrivate, "links/{folderID}/{documentID}/{pageID}", []string{"GET", "OPTIONS"}, nil, GetLinkCandidates))
|
||||||
|
log.IfErr(Add(RoutePrefixPrivate, "links", []string{"GET", "OPTIONS"}, nil, SearchLinkCandidates))
|
||||||
|
|
||||||
// Global installation-wide config
|
// Global installation-wide config
|
||||||
log.IfErr(Add(RoutePrefixPrivate, "global", []string{"GET", "OPTIONS"}, nil, GetGlobalConfig))
|
log.IfErr(Add(RoutePrefixPrivate, "global", []string{"GET", "OPTIONS"}, nil, GetGlobalConfig))
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/documize/community/core/api/entity"
|
"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/log"
|
||||||
"github.com/documize/community/core/utility"
|
"github.com/documize/community/core/utility"
|
||||||
)
|
)
|
||||||
|
@ -45,53 +46,188 @@ func (p *Persister) AddContentLink(l entity.Link) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SearchLinkCandidates returns matching documents, sections and attachments using keywords.
|
||||||
|
func (p *Persister) SearchLinkCandidates(keywords string) (docs []entity.LinkCandidate,
|
||||||
|
pages []entity.LinkCandidate, attachments []entity.LinkCandidate, err error) {
|
||||||
|
|
||||||
|
err = nil
|
||||||
|
|
||||||
|
// find matching documents
|
||||||
|
temp := []entity.LinkCandidate{}
|
||||||
|
likeQuery := "title LIKE '%" + keywords + "%'"
|
||||||
|
|
||||||
|
err = Db.Select(&temp,
|
||||||
|
`SELECT refid as documentid, labelid as folderid,title from document WHERE orgid=? AND `+likeQuery+` AND labelid IN
|
||||||
|
(SELECT refid from label WHERE orgid=? AND type=2 AND userid=?
|
||||||
|
UNION ALL SELECT refid FROM label a where orgid=? AND type=1 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1))
|
||||||
|
UNION ALL SELECT refid FROM label a where orgid=? AND type=3 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1)))
|
||||||
|
ORDER BY title`,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.UserID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.UserID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Unable to execute search links for org %s", p.Context.OrgID), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range temp {
|
||||||
|
c := entity.LinkCandidate{
|
||||||
|
RefID: util.UniqueID(),
|
||||||
|
FolderID: r.FolderID,
|
||||||
|
DocumentID: r.DocumentID,
|
||||||
|
TargetID: r.DocumentID,
|
||||||
|
LinkType: "document",
|
||||||
|
Title: r.Title,
|
||||||
|
Context: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
docs = append(docs, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// find matching sections
|
||||||
|
likeQuery = "p.title LIKE '%" + keywords + "%'"
|
||||||
|
temp = []entity.LinkCandidate{}
|
||||||
|
|
||||||
|
err = Db.Select(&temp,
|
||||||
|
`SELECT p.refid as targetid, p.documentid as documentid, p.title as title, d.title as context, d.labelid as folderid from page p
|
||||||
|
LEFT JOIN document d ON d.refid=p.documentid WHERE p.orgid=? AND `+likeQuery+` AND d.labelid IN
|
||||||
|
(SELECT refid from label WHERE orgid=? AND type=2 AND userid=?
|
||||||
|
UNION ALL SELECT refid FROM label a where orgid=? AND type=1 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1))
|
||||||
|
UNION ALL SELECT refid FROM label a where orgid=? AND type=3 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1)))
|
||||||
|
ORDER BY p.title`,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.UserID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.UserID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Unable to execute search links for org %s", p.Context.OrgID), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range temp {
|
||||||
|
c := entity.LinkCandidate{
|
||||||
|
RefID: util.UniqueID(),
|
||||||
|
FolderID: r.FolderID,
|
||||||
|
DocumentID: r.DocumentID,
|
||||||
|
TargetID: r.TargetID,
|
||||||
|
LinkType: "section",
|
||||||
|
Title: r.Title,
|
||||||
|
Context: r.Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
pages = append(pages, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
// find matching attachments
|
||||||
|
likeQuery = "a.filename LIKE '%" + keywords + "%'"
|
||||||
|
temp = []entity.LinkCandidate{}
|
||||||
|
|
||||||
|
err = Db.Select(&temp,
|
||||||
|
`SELECT a.refid as targetid, a.documentid as documentid, a.filename as title, a.extension as context, d.labelid as folderid from attachment a
|
||||||
|
LEFT JOIN document d ON d.refid=a.documentid WHERE a.orgid=? AND `+likeQuery+` AND d.labelid IN
|
||||||
|
(SELECT refid from label WHERE orgid=? AND type=2 AND userid=?
|
||||||
|
UNION ALL SELECT refid FROM label a where orgid=? AND type=1 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid='' AND (canedit=1 OR canview=1))
|
||||||
|
UNION ALL SELECT refid FROM label a where orgid=? AND type=3 AND refid IN (SELECT labelid from labelrole WHERE orgid=? AND userid=? AND (canedit=1 OR canview=1)))
|
||||||
|
ORDER BY a.filename`,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.UserID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.OrgID,
|
||||||
|
p.Context.UserID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Error(fmt.Sprintf("Unable to execute search links for org %s", p.Context.OrgID), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, r := range temp {
|
||||||
|
c := entity.LinkCandidate{
|
||||||
|
RefID: util.UniqueID(),
|
||||||
|
FolderID: r.FolderID,
|
||||||
|
DocumentID: r.DocumentID,
|
||||||
|
TargetID: r.TargetID,
|
||||||
|
LinkType: "file",
|
||||||
|
Title: r.Title,
|
||||||
|
Context: r.Context,
|
||||||
|
}
|
||||||
|
|
||||||
|
attachments = append(attachments, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(docs) == 0 {
|
||||||
|
docs = []entity.LinkCandidate{}
|
||||||
|
}
|
||||||
|
if len(pages) == 0 {
|
||||||
|
pages = []entity.LinkCandidate{}
|
||||||
|
}
|
||||||
|
if len(attachments) == 0 {
|
||||||
|
attachments = []entity.LinkCandidate{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// GetReferencedLinks returns all links that the specified section is referencing.
|
// GetReferencedLinks returns all links that the specified section is referencing.
|
||||||
func (p *Persister) GetReferencedLinks(sectionID string) (links []entity.Link, err error) {
|
// func (p *Persister) GetReferencedLinks(sectionID string) (links []entity.Link, err error) {
|
||||||
err = nil
|
// err = nil
|
||||||
|
//
|
||||||
sql := "SELECT id,refid,orgid,folderid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND sourceid=?"
|
// sql := "SELECT id,refid,orgid,folderid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND sourceid=?"
|
||||||
|
//
|
||||||
err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
|
// err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
|
// log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// GetContentLinksForSection returns all links that are linking to the specified section.
|
// // GetContentLinksForSection returns all links that are linking to the specified section.
|
||||||
func (p *Persister) GetContentLinksForSection(sectionID string) (links []entity.Link, err error) {
|
// func (p *Persister) GetContentLinksForSection(sectionID string) (links []entity.Link, err error) {
|
||||||
err = nil
|
// err = nil
|
||||||
|
//
|
||||||
sql := "SELECT id,refid,orgid,folderid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND sectionid=?"
|
// sql := "SELECT id,refid,orgid,folderid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND sectionid=?"
|
||||||
|
//
|
||||||
err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
|
// err = Db.Select(&links, sql, p.Context.OrgID, sectionID)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
|
// log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// GetContentLinksForDocument returns all links that are linking to the specified document.
|
// // GetContentLinksForDocument returns all links that are linking to the specified document.
|
||||||
func (p *Persister) GetContentLinksForDocument(documentID string) (links []entity.Link, err error) {
|
// func (p *Persister) GetContentLinksForDocument(documentID string) (links []entity.Link, err error) {
|
||||||
err = nil
|
// err = nil
|
||||||
|
//
|
||||||
sql := "SELECT id,refid,orgid,folderid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND documentid=?"
|
// sql := "SELECT id,refid,orgid,folderid,userid,sourceid,documentid,targetid,linktype,orphan,created,revised from link WHERE orgid=? AND documentid=?"
|
||||||
|
//
|
||||||
err = Db.Select(&links, sql, p.Context.OrgID, documentID)
|
// err = Db.Select(&links, sql, p.Context.OrgID, documentID)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
|
// log.Error(fmt.Sprintf("Unable to execute select links for org %s", p.Context.OrgID), err)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
// MarkOrphanContentLink marks the link record as being invalid.
|
// MarkOrphanContentLink marks the link record as being invalid.
|
||||||
func (p *Persister) MarkOrphanContentLink(l entity.Link) (err error) {
|
func (p *Persister) MarkOrphanContentLink(l entity.Link) (err error) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue