FEATURE: Rename from Knowledge Explorer to Docs (#27)

After internal discussion, the team decided to rename this plugin to `discourse-docs`. No substantial changes made here aside from a settings migration.
This commit is contained in:
Justin DiRose 2021-01-18 10:38:09 -06:00 committed by GitHub
parent cb7c12defe
commit f32aebdba0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 221 additions and 215 deletions

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
module KnowledgeExplorer module Docs
class KnowledgeExplorerController < ApplicationController class DocsController < ApplicationController
requires_plugin 'knowledge-explorer' requires_plugin 'docs'
skip_before_action :check_xhr, only: [:index] skip_before_action :check_xhr, only: [:index]
@ -18,7 +18,7 @@ module KnowledgeExplorer
page: params[:page] page: params[:page]
} }
query = KnowledgeExplorer::Query.new(current_user, filters).list query = Docs::Query.new(current_user, filters).list
if filters[:topic].present? if filters[:topic].present?
begin begin
@ -45,7 +45,7 @@ module KnowledgeExplorer
end end
def get_topic(topic, current_user) def get_topic(topic, current_user)
return nil unless topic_in_explorer(topic.category_id, topic.tags) return nil unless topic_in_docs(topic.category_id, topic.tags)
topic_view = TopicView.new(topic.id, current_user) topic_view = TopicView.new(topic.id, current_user)
guardian = Guardian.new(current_user) guardian = Guardian.new(current_user)
@ -53,13 +53,12 @@ module KnowledgeExplorer
TopicViewSerializer.new(topic_view, scope: guardian, root: false) TopicViewSerializer.new(topic_view, scope: guardian, root: false)
end end
def topic_in_explorer(category, tags) def topic_in_docs(category, tags)
category_match = KnowledgeExplorer::Query.categories.include?(category.to_s) category_match = Docs::Query.categories.include?(category.to_s)
tags = tags.pluck(:name) tags = tags.pluck(:name)
tag_match = KnowledgeExplorer::Query.tags.any? { |tag| tags.include?(tag) } tag_match = Docs::Query.tags.any? { |tag| tags.include?(tag) }
category_match || tag_match category_match || tag_match
end end
end end
end end

View File

@ -0,0 +1,4 @@
<%- if SiteSetting.docs_enabled%>
User-agent: *
Disallow: /docs/
<% end %>

View File

@ -1,4 +0,0 @@
<%- if SiteSetting.knowledge_explorer_enabled %>
User-agent: *
Disallow: /knowledge-explorer/
<% end %>

View File

@ -3,7 +3,7 @@ import { debounce } from "@ember/runloop";
import discourseDebounce from "discourse-common/lib/debounce"; import discourseDebounce from "discourse-common/lib/debounce";
export default Component.extend({ export default Component.extend({
classNames: "knowledge-explorer-search", classNames: "docs-search",
debouncedSearch(term) { debouncedSearch(term) {
// TODO: Use discouseDebounce when discourse 2.7 gets released. // TODO: Use discouseDebounce when discourse 2.7 gets released.

View File

@ -2,7 +2,7 @@ import Component from "@ember/component";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
classNames: "knowledge-explorer-topic-list", classNames: "docs-topic-list",
@discourseComputed("order") @discourseComputed("order")
sortTitle(order) { sortTitle(order) {
return order === "title"; return order === "title";
@ -15,7 +15,7 @@ export default Component.extend({
// need to handle clicks here since links are in a raw view // need to handle clicks here since links are in a raw view
click(e) { click(e) {
if (e.target.classList.contains("knowledge-explorer-topic-link")) { if (e.target.classList.contains("docs-topic-link")) {
const topicId = e.target.dataset.topicId; const topicId = e.target.dataset.topicId;
this.selectTopic(topicId); this.selectTopic(topicId);
return false; return false;

View File

@ -3,7 +3,7 @@ import { reads } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
export default Component.extend({ export default Component.extend({
classNames: "knowledge-explorer-topic", classNames: "docs-topic",
originalPostContent: reads("post.cooked"), originalPostContent: reads("post.cooked"),
@ -27,16 +27,12 @@ export default Component.extend({
didInsertElement() { didInsertElement() {
this._super(...arguments); this._super(...arguments);
document document.querySelector("body").classList.add("archetype-docs-topic");
.querySelector("body")
.classList.add("archetype-knowledge-explorer-topic");
}, },
willDestroyElement() { willDestroyElement() {
this._super(...arguments); this._super(...arguments);
document document.querySelector("body").classList.remove("archetype-docs-topic");
.querySelector("body")
.classList.remove("archetype-knowledge-explorer-topic");
}, },
}); });

View File

@ -3,7 +3,7 @@ import { inject } from "@ember/controller";
import discourseComputed from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { alias, readOnly, equal } from "@ember/object/computed"; import { alias, readOnly, equal } from "@ember/object/computed";
import { on } from "discourse-common/utils/decorators"; import { on } from "discourse-common/utils/decorators";
import KnowledgeExplorer from "discourse/plugins/discourse-knowledge-explorer/discourse/models/knowledge-explorer"; import Docs from "discourse/plugins/discourse-docs/discourse/models/docs";
import { getOwner } from "@ember/application"; import { getOwner } from "@ember/application";
export default Controller.extend({ export default Controller.extend({
@ -69,7 +69,7 @@ export default Controller.extend({
canFilterSolved() { canFilterSolved() {
return ( return (
this.siteSettings.solved_enabled && this.siteSettings.solved_enabled &&
this.siteSettings.knowledge_explorer_add_solved_filter this.siteSettings.docs_add_solved_filter
); );
}, },
@ -157,7 +157,7 @@ export default Controller.extend({
if (this.canLoadMore && !this.isLoadingMore) { if (this.canLoadMore && !this.isLoadingMore) {
this.set("isLoadingMore", true); this.set("isLoadingMore", true);
KnowledgeExplorer.loadMore(this.loadMoreUrl).then((result) => { Docs.loadMore(this.loadMoreUrl).then((result) => {
const topics = this.topics.concat(result.topics.topic_list.topics); const topics = this.topics.concat(result.topics.topic_list.topics);
this.setProperties({ this.setProperties({
@ -179,7 +179,7 @@ export default Controller.extend({
returnToList() { returnToList() {
this.set("selectedTopic", null); this.set("selectedTopic", null);
getOwner(this).lookup("router:main").transitionTo("knowledgeExplorer"); getOwner(this).lookup("router:main").transitionTo("docs");
}, },
}, },
}); });

View File

@ -2,7 +2,7 @@ import Controller from "@ember/controller";
import { inject } from "@ember/controller"; import { inject } from "@ember/controller";
export default Controller.extend({ export default Controller.extend({
indexController: inject("knowledgeExplorer.index"), indexController: inject("docs.index"),
actions: { actions: {
updateSelectedCategories(category) { updateSelectedCategories(category) {
this.indexController.send("updateSelectedCategories", category); this.indexController.send("updateSelectedCategories", category);

View File

@ -1,5 +1,5 @@
export default function () { export default function () {
this.route("knowledgeExplorer", { path: "/docs" }, function () { this.route("docs", { path: "/docs" }, function () {
this.route("index", { path: "/" }); this.route("index", { path: "/" });
}); });
} }

View File

@ -3,9 +3,9 @@ import { withPluginApi } from "discourse/lib/plugin-api";
function initialize(api) { function initialize(api) {
api.decorateWidget("hamburger-menu:generalLinks", () => { api.decorateWidget("hamburger-menu:generalLinks", () => {
return { return {
route: "knowledgeExplorer", route: "docs",
label: "knowledge_explorer.title", label: "docs.title",
className: "knowledge-explorer-link", className: "docs-link",
}; };
}); });
@ -13,11 +13,11 @@ function initialize(api) {
} }
export default { export default {
name: "setup-knowledge-explorer", name: "setup-docs",
initialize(container) { initialize(container) {
const siteSettings = container.lookup("site-settings:main"); const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.knowledge_explorer_enabled) { if (!siteSettings.docs_enabled) {
return; return;
} }
withPluginApi("0.8", (api) => initialize(api)); withPluginApi("0.8", (api) => initialize(api));

View File

@ -2,9 +2,9 @@ import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import Topic from "discourse/models/topic"; import Topic from "discourse/models/topic";
const KnowledgeExplorer = EmberObject.extend({}); const Docs = EmberObject.extend({});
KnowledgeExplorer.reopenClass({ Docs.reopenClass({
list(params) { list(params) {
let filters = []; let filters = [];
if (params.filterCategories) { if (params.filterCategories) {
@ -65,4 +65,4 @@ KnowledgeExplorer.reopenClass({
}, },
}); });
export default KnowledgeExplorer; export default Docs;

View File

@ -1,6 +1,6 @@
import DiscourseRoute from "discourse/routes/discourse"; import DiscourseRoute from "discourse/routes/discourse";
import I18n from "I18n"; import I18n from "I18n";
import KnowledgeExplorer from "discourse/plugins/discourse-knowledge-explorer/discourse/models/knowledge-explorer"; import Docs from "discourse/plugins/discourse-docs/discourse/models/docs";
export default DiscourseRoute.extend({ export default DiscourseRoute.extend({
queryParams: { queryParams: {
@ -16,16 +16,16 @@ export default DiscourseRoute.extend({
}, },
}, },
model(params) { model(params) {
this.controllerFor("knowledgeExplorer.index").set("isLoading", true); this.controllerFor("docs.index").set("isLoading", true);
return KnowledgeExplorer.list(params).then((result) => { return Docs.list(params).then((result) => {
this.controllerFor("knowledgeExplorer.index").set("isLoading", false); this.controllerFor("docs.index").set("isLoading", false);
return result; return result;
}); });
}, },
titleToken() { titleToken() {
const model = this.currentModel; const model = this.currentModel;
const pageTitle = I18n.t("knowledge_explorer.title"); const pageTitle = I18n.t("docs.title");
if (model.topic.title && model.topic.category_id) { if (model.topic.title && model.topic.category_id) {
const categoryName = this.site.categories.findBy( const categoryName = this.site.categories.findBy(
"id", "id",

View File

@ -0,0 +1,10 @@
<a {{action "selectCategory"}} class="docs-item docs-category {{if category.active 'selected'}}">
{{#unless category.active}}
{{d-icon "plus"}}
{{/unless}}
{{#if category.active}}
{{d-icon "times-circle"}}
{{/if}}
<span class="docs-item-id category-id">{{categoryName}}</span>
<span class="docs-item-count category-count">{{category.count}}</span>
</a>

View File

@ -1,16 +1,16 @@
<span class="knowledge-explorer-search-wrapper"> <span class="docs-search-wrapper">
{{input {{input
type="text" type="text"
value=(readonly searchTerm) value=(readonly searchTerm)
input=(action "onSearchTermChange" value="target.value") input=(action "onSearchTermChange" value="target.value")
class="no-blur knowledge-explorer-search-bar" class="no-blur docs-search-bar"
autocorrect="off" autocorrect="off"
placeholder=(i18n "knowledge_explorer.search.placeholder") placeholder=(i18n "docs.search.placeholder")
autocapitalize="off" autocapitalize="off"
}} }}
{{#if searchTerm}} {{#if searchTerm}}
{{d-button action=(action "clearSearch") class="clear-search" label="knowledge_explorer.search.clear"}} {{d-button action=(action "clearSearch") class="clear-search" label="docs.search.clear"}}
{{else}} {{else}}
{{d-icon "search"}} {{d-icon "search"}}
{{/if}} {{/if}}

View File

@ -0,0 +1,10 @@
<a {{action "selectTag"}} class="docs-item docs-tag {{if tag.active 'selected'}} {{if subtag 'subtag'}}">
{{#unless tag.active}}
{{d-icon "plus"}}
{{/unless}}
{{#if tag.active}}
{{d-icon "times-circle"}}
{{/if}}
<span class="docs-item-id tag-id">{{tag.id}}</span>
<span class="docs-item-count tag-count">{{tag.count}}</span>
</a>

View File

@ -2,7 +2,7 @@
<table class="topic-list"> <table class="topic-list">
<thead> <thead>
<th {{action "sortListTitle"}}> <th {{action "sortListTitle"}}>
{{i18n 'knowledge_explorer.column_titles.topic'}} {{i18n 'docs.column_titles.topic'}}
{{#if sortTitle}} {{#if sortTitle}}
{{#if ascending}} {{#if ascending}}
{{d-icon 'angle-up'}} {{d-icon 'angle-up'}}
@ -12,7 +12,7 @@
{{/if}} {{/if}}
</th> </th>
<th {{action "sortListActivity"}}> <th {{action "sortListActivity"}}>
{{i18n 'knowledge_explorer.column_titles.activity'}} {{i18n 'docs.column_titles.activity'}}
{{#if sortActivity}} {{#if sortActivity}}
{{#if ascending}} {{#if ascending}}
{{d-icon 'angle-up'}} {{d-icon 'angle-up'}}
@ -24,7 +24,7 @@
</thead> </thead>
<tbody> <tbody>
{{#each topics as |topic|}} {{#each topics as |topic|}}
{{raw "knowledge-explorer-topic-list-item" topic=topic}} {{raw "docs-topic-list-item" topic=topic}}
{{/each}} {{/each}}
</tbody> </tbody>
</table> </table>

View File

@ -0,0 +1,22 @@
{{d-button
label="docs.topic.back"
class="docs-nav-link return"
action=return
}}
<div class="topic-content">
<h1>{{topic.unicode_title}}</h1>
{{mount-widget
widget="post"
model=model
args=post
}}
{{share-popup topic=model.topic}}
</div>
<a class="docs-nav-link more" href="/t/{{topic.id}}">
{{d-icon "far-comment"}} {{i18n 'docs.topic.navigate_to_topic'}}
</a>
{{plugin-outlet name="after-docs-topic"}}

View File

@ -1,10 +0,0 @@
<a {{action "selectCategory"}} class="knowledge-explorer-item knowledge-explorer-category {{if category.active 'selected'}}">
{{#unless category.active}}
{{d-icon "plus"}}
{{/unless}}
{{#if category.active}}
{{d-icon "times-circle"}}
{{/if}}
<span class="knowledge-explorer-item-id category-id">{{categoryName}}</span>
<span class="knowledge-explorer-item-count category-count">{{category.count}}</span>
</a>

View File

@ -1,10 +0,0 @@
<a {{action "selectTag"}} class="knowledge-explorer-item knowledge-explorer-tag {{if tag.active 'selected'}} {{if subtag 'subtag'}}">
{{#unless tag.active}}
{{d-icon "plus"}}
{{/unless}}
{{#if tag.active}}
{{d-icon "times-circle"}}
{{/if}}
<span class="knowledge-explorer-item-id tag-id">{{tag.id}}</span>
<span class="knowledge-explorer-item-count tag-count">{{tag.count}}</span>
</a>

View File

@ -1,22 +0,0 @@
{{d-button
label="knowledge_explorer.topic.back"
class="knowledge-explorer-nav-link return"
action=return
}}
<div class="topic-content">
<h1>{{topic.unicode_title}}</h1>
{{mount-widget
widget="post"
model=model
args=post
}}
{{share-popup topic=model.topic}}
</div>
<a class="knowledge-explorer-nav-link more" href="/t/{{topic.id}}">
{{d-icon "far-comment"}} {{i18n 'knowledge_explorer.topic.navigate_to_topic'}}
</a>
{{plugin-outlet name="after-knowledge-explorer-topic"}}

View File

@ -1,33 +1,33 @@
{{#conditional-loading-spinner condition=isLoading}} {{#conditional-loading-spinner condition=isLoading}}
{{#if emptyTopics}} {{#if emptyTopics}}
<span class="no-topics-found">{{html-safe (i18n 'knowledge_explorer.no_topics')}}</span> <span class="no-topics-found">{{html-safe (i18n 'docs.no_topics')}}</span>
{{else}} {{else}}
<div class="knowledge-explorer-browse"> <div class="docs-browse">
{{#if site.mobileView}} {{#if site.mobileView}}
{{#unless selectedTopic}} {{#unless selectedTopic}}
{{d-button class="knowledge-explorer-expander" icon=(if expandedFilters "angle-up" "angle-down") action=(action "toggleFilters") label="knowledge_explorer.filter_button"}} {{d-button class="docs-expander" icon=(if expandedFilters "angle-up" "angle-down") action=(action "toggleFilters") label="docs.filter_button"}}
{{/unless}} {{/unless}}
{{/if}} {{/if}}
<div class="knowledge-explorer-filters"> <div class="docs-filters">
{{#if expandedFilters}} {{#if expandedFilters}}
{{#if canFilterSolved}} {{#if canFilterSolved}}
<div class="knowledge-explorer-items knowledge-explorer-solved"> <div class="docs-items docs-solved">
<label class="checkbox-label knowledge-explorer-item"> <label class="checkbox-label docs-item">
{{input {{input
type="checkbox" type="checkbox"
checked=(readonly filterSolved) checked=(readonly filterSolved)
change=(action "onChangeFilterSolved" value="target.checked") change=(action "onChangeFilterSolved" value="target.checked")
}} }}
{{i18n "knowledge_explorer.filter_solved"}} {{i18n "docs.filter_solved"}}
</label> </label>
</div> </div>
{{/if}} {{/if}}
{{#if categories}} {{#if categories}}
<div class="knowledge-explorer-items knowledge-explorer-categories"> <div class="docs-items docs-categories">
<h3>{{i18n 'knowledge_explorer.categories'}}</h3> <h3>{{i18n 'docs.categories'}}</h3>
{{#each categories as |category|}} {{#each categories as |category|}}
{{knowledge-explorer-category {{docs-category
category=category category=category
selectCategory=(action "updateSelectedCategories" selectCategory=(action "updateSelectedCategories"
tagName="") tagName="")
@ -36,10 +36,10 @@
</div> </div>
{{/if}} {{/if}}
{{#if tags}} {{#if tags}}
<div class="knowledge-explorer-items knowledge-explorer-tags"> <div class="docs-items docs-tags">
<h3>{{i18n 'knowledge_explorer.tags'}}</h3> <h3>{{i18n 'docs.tags'}}</h3>
{{#each tags as |tag|}} {{#each tags as |tag|}}
{{knowledge-explorer-tag {{docs-tag
tag=tag tag=tag
selectTag=(action "updateSelectedTags") selectTag=(action "updateSelectedTags")
}} }}
@ -50,26 +50,26 @@
</div> </div>
{{#if selectedTopic}} {{#if selectedTopic}}
{{#conditional-loading-spinner condition=isTopicLoading}} {{#conditional-loading-spinner condition=isTopicLoading}}
{{knowledge-explorer-topic topic=topic return=(action "returnToList")}} {{docs-topic topic=topic return=(action "returnToList")}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}
{{else}} {{else}}
<div class="knowledge-explorer-results"> <div class="docs-results">
{{#if isSearchingOrFiltered}} {{#if isSearchingOrFiltered}}
{{#if emptyResults}} {{#if emptyResults}}
<div class="result-count no-result"> <div class="result-count no-result">
{{i18n 'search.no_results'}} {{i18n 'search.no_results'}}
</div> </div>
{{plugin-outlet name="after-knowledge-explorer-empty-results"}} {{plugin-outlet name="after-docs-empty-results"}}
{{else}} {{else}}
<div class="result-count"> <div class="result-count">
{{i18n 'knowledge_explorer.search.results' {{i18n 'docs.search.results'
count=topicCount count=topicCount
}} }}
</div> </div>
{{/if}} {{/if}}
{{/if}} {{/if}}
{{#unless emptyResults}} {{#unless emptyResults}}
{{knowledge-explorer-topic-list {{docs-topic-list
topics=topics topics=topics
ascending=ascending ascending=ascending
order=orderColumn order=orderColumn

View File

@ -0,0 +1 @@
<a data-topic-id="{{topic.id}}" class="docs-topic-link">{{{topic.fancyTitle}}}</a>

View File

@ -2,7 +2,7 @@
<td class="main-link"> <td class="main-link">
<span class="link-top-line"> <span class="link-top-line">
{{~raw "topic-status" topic=topic}} {{~raw "topic-status" topic=topic}}
{{~raw "knowledge-explorer-topic-link" topic=topic}} {{~raw "docs-topic-link" topic=topic}}
</span> </span>
<span class="link-bottom-line"> <span class="link-bottom-line">
{{category-link topic.category}} {{category-link topic.category}}

View File

@ -0,0 +1,9 @@
<div class="docs">
{{plugin-outlet name="before-docs-search" args=(hash selectCategory=(action "updateSelectedCategories"))}}
{{docs-search
searchTerm=(readonly indexController.searchTerm)
onSearch=(action "performSearch")
}}
{{outlet}}
</div>

View File

@ -1 +0,0 @@
<a data-topic-id="{{topic.id}}" class="knowledge-explorer-topic-link">{{{topic.fancyTitle}}}</a>

View File

@ -1,9 +0,0 @@
<div class="knowledge-explorer">
{{plugin-outlet name="before-knowledge-explorer-search" args=(hash selectCategory=(action "updateSelectedCategories"))}}
{{knowledge-explorer-search
searchTerm=(readonly indexController.searchTerm)
onSearch=(action "performSearch")
}}
{{outlet}}
</div>

View File

@ -1,4 +1,4 @@
.knowledge-explorer-search-wrapper { .docs-search-wrapper {
position: relative; position: relative;
width: 500px; width: 500px;
.d-icon { .d-icon {
@ -24,7 +24,7 @@
} }
} }
.knowledge-explorer-search { .docs-search {
align-items: center; align-items: center;
background-color: var(--primary-very-low, $primary-very-low); background-color: var(--primary-very-low, $primary-very-low);
display: flex; display: flex;
@ -34,20 +34,20 @@
// More breathing room on larger screens // More breathing room on larger screens
margin-bottom: 2em; margin-bottom: 2em;
} }
.knowledge-explorer-search-bar { .docs-search-bar {
height: 50px; height: 50px;
margin-bottom: 0px; margin-bottom: 0px;
width: 100%; width: 100%;
} }
} }
.knowledge-explorer-browse { .docs-browse {
display: flex; display: flex;
.loading-container { .loading-container {
display: flex; display: flex;
flex-basis: 100%; flex-basis: 100%;
padding: 0.625em 0 0.625em 0.625em; padding: 0.625em 0 0.625em 0.625em;
} }
.knowledge-explorer-results { .docs-results {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex-basis: 100%; flex-basis: 100%;
@ -56,7 +56,7 @@
padding-left: 0.625em; padding-left: 0.625em;
} }
} }
.knowledge-explorer-filters { .docs-filters {
margin-top: 0.15em; margin-top: 0.15em;
flex: 0 1 20%; flex: 0 1 20%;
@include breakpoint(tablet, min-width) { @include breakpoint(tablet, min-width) {
@ -66,7 +66,7 @@
// be more narrow than content if needed // be more narrow than content if needed
min-width: 175px; min-width: 175px;
} }
.knowledge-explorer-items { .docs-items {
padding: 0.57em 1em 1em 0; padding: 0.57em 1em 1em 0;
a { a {
@ -79,13 +79,13 @@
font-size: $font-up-1; font-size: $font-up-1;
} }
.knowledge-explorer-item-count { .docs-item-count {
margin-left: auto; margin-left: auto;
color: var(--primary-high, $primary-high); color: var(--primary-high, $primary-high);
font-size: $font-down-1; font-size: $font-down-1;
} }
.knowledge-explorer-item { .docs-item {
display: flex; display: flex;
align-items: center; align-items: center;
cursor: pointer; cursor: pointer;
@ -121,7 +121,7 @@
font-weight: bold; font-weight: bold;
} }
} }
.knowledge-explorer-topic-list { .docs-topic-list {
flex-basis: 100%; flex-basis: 100%;
th { th {
@ -145,7 +145,7 @@
font-weight: normal; font-weight: normal;
font-size: $font-down-1; font-size: $font-down-1;
} }
.knowledge-explorer-topic-link { .docs-topic-link {
color: var(--tertiary, $tertiary); color: var(--tertiary, $tertiary);
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
@ -154,10 +154,10 @@
} }
} }
} }
.knowledge-explorer-topic { .docs-topic {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.knowledge-explorer-nav-link { .docs-nav-link {
font-weight: 700; font-weight: 700;
&.return { &.return {
align-items: center; align-items: center;

View File

@ -1,60 +1,60 @@
.mobile-view { .mobile-view {
.knowledge-explorer { .docs {
.knowledge-explorer-search-wrapper { .docs-search-wrapper {
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
.knowledge-explorer-search { .docs-search {
font-size: $font-up-2; font-size: $font-up-2;
padding: 0.5em 0; padding: 0.5em 0;
.knowledge-explorer-search-bar { .docs-search-bar {
width: calc(100vw - 2em); width: calc(100vw - 2em);
} }
} }
.knowledge-explorer-browse { .docs-browse {
.knowledge-explorer-items { .docs-items {
padding-right: 0; padding-right: 0;
} }
flex-direction: column; flex-direction: column;
.knowledge-explorer-results .result-count { .docs-results .result-count {
padding-left: 0; padding-left: 0;
} }
.knowledge-explorer-topic-list { .docs-topic-list {
flex-basis: 100%; flex-basis: 100%;
} }
.knowledge-explorer-topic-link { .docs-topic-link {
padding-right: 0.25em; padding-right: 0.25em;
} }
.loading-container { .loading-container {
padding: 0.625em 0; padding: 0.625em 0;
} }
.knowledge-explorer-topic { .docs-topic {
width: calc(100vw - 20px); width: calc(100vw - 20px);
} }
} }
} }
.knowledge-explorer-filters { .docs-filters {
margin-top: 0; margin-top: 0;
background: var(--primary-very-low, $primary-very-low); background: var(--primary-very-low, $primary-very-low);
padding: 0 0.5em; padding: 0 0.5em;
.knowledge-explorer-items:first-of-type { .docs-items:first-of-type {
margin-top: 1em; margin-top: 1em;
} }
+ .knowledge-explorer-results { + .docs-results {
margin-top: 2em; margin-top: 2em;
} }
} }
.archetype-knowledge-explorer-topic { .archetype-docs-topic {
.knowledge-explorer-filters { .docs-filters {
display: none; display: none;
} }
} }
.knowledge-explorer-expander { .docs-expander {
margin: 1em 0 0 0; margin: 1em 0 0 0;
width: 100%; width: 100%;
} }

View File

@ -1,11 +1,11 @@
en: en:
js: js:
knowledge_explorer: docs:
title: "Knowledge Explorer" title: "Docs"
column_titles: column_titles:
topic: "Topic" topic: "Topic"
activity: "Activity" activity: "Activity"
no_topics: "No topics in Knowledge Explorer." no_topics: "No topics in Docs."
categories: "Categories" categories: "Categories"
tags: "Tags" tags: "Tags"
search: search:

View File

@ -1,6 +1,6 @@
en: en:
site_settings: site_settings:
knowledge_explorer_enabled: "Enable the Knowledge Explorer Plugin" docs_enabled: "Enable the Docs Plugin"
knowledge_explorer_categories: "A list of category slugs to include in the knowledge explorer" docs_categories: "A list of category slugs to include in docs"
knowledge_explorer_tags: "A list of tags to include in the knowledge explorer" docs_tags: "A list of tags to include in docs"
knowledge_explorer_add_solved_filter: "Adds a filter for solved topics -- requires Discourse Solved to be installed and enabled" docs_add_solved_filter: "Adds a filter for solved topics -- requires Discourse Solved to be installed and enabled"

View File

@ -1,8 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
require_dependency 'knowledge_explorer_constraint' require_dependency 'docs_constraint'
KnowledgeExplorer::Engine.routes.draw do Docs::Engine.routes.draw do
get '/' => 'knowledge_explorer#index', constraints: KnowledgeExplorerConstraint.new get '/' => 'docs#index', constraints: DocsConstraint.new
get '.json' => 'knowledge_explorer#index', constraints: KnowledgeExplorerConstraint.new get '.json' => 'docs#index', constraints: DocsConstraint.new
end end

View File

@ -1,15 +1,15 @@
plugins: plugins:
knowledge_explorer_enabled: docs_enabled:
default: false default: false
client: true client: true
knowledge_explorer_categories: docs_categories:
type: category_list type: category_list
default: "" default: ""
client: true client: true
knowledge_explorer_tags: docs_tags:
type: tag_list type: tag_list
default: "" default: ""
client: true client: true
knowledge_explorer_add_solved_filter: docs_add_solved_filter:
default: false default: false
client: true client: true

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
#
class RenameKnowledgeExplorerSettings < ActiveRecord::Migration[6.0]
def up
execute "UPDATE site_settings SET name = 'docs_enabled' WHERE name = 'knowledge_explorer_enabled'"
execute "UPDATE site_settings SET name = 'docs_categories' WHERE name = 'knowledge_explorer_categories'"
execute "UPDATE site_settings SET name = 'docs_tags' WHERE name = 'knowledge_explorer_tags'"
execute "UPDATE site_settings SET name = 'docs_add_solved_filter' WHERE name = 'knowledge_explorer_add_solved_filter'"
end
def down
execute "UPDATE site_settings SET name = 'knowledge_explorer_enabled' WHERE name = 'docs_enabled'"
execute "UPDATE site_settings SET name = 'knowledge_explorer_categories' WHERE name = 'docs_categories'"
execute "UPDATE site_settings SET name = 'knowledge_explorer_tags' WHERE name = 'docs_tags'"
execute "UPDATE site_settings SET name = 'knowledge_explorer_add_solved_filter' WHERE name = 'docs_add_solved_filter'"
end
end

View File

@ -1,12 +1,12 @@
# frozen_string_literal: true # frozen_string_literal: true
module ::KnowledgeExplorer module ::Docs
class Engine < ::Rails::Engine class Engine < ::Rails::Engine
isolate_namespace KnowledgeExplorer isolate_namespace Docs
config.after_initialize do config.after_initialize do
Discourse::Application.routes.append do Discourse::Application.routes.append do
mount ::KnowledgeExplorer::Engine, at: '/docs' mount ::Docs::Engine, at: '/docs'
get '/knowledge-explorer', to: redirect("/docs") get '/knowledge-explorer', to: redirect("/docs")
end end
end end

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true # frozen_string_literal: true
module KnowledgeExplorer module Docs
class Query class Query
def initialize(user = nil, filters = {}) def initialize(user = nil, filters = {})
@user = user @user = user
@ -9,18 +9,18 @@ module KnowledgeExplorer
end end
def self.categories def self.categories
SiteSetting.knowledge_explorer_categories.split('|') SiteSetting.docs_categories.split('|')
end end
def self.tags def self.tags
SiteSetting.knowledge_explorer_tags.split('|') SiteSetting.docs_tags.split('|')
end end
def list def list
# query for topics matching selected categories & tags # query for topics matching selected categories & tags
opts = { no_definitions: true, limit: false } opts = { no_definitions: true, limit: false }
tq = TopicQuery.new(@user, opts) tq = TopicQuery.new(@user, opts)
results = tq.list_knowledge_explorer_topics results = tq.list_docs_topics
results = results.left_outer_joins(:tags) results = results.left_outer_joins(:tags)
results = results.references(:categories) results = results.references(:categories)
results = results.where('topics.category_id IN (?)', Query.categories).or(results.where('tags.name IN (?)', Query.tags)) results = results.where('topics.category_id IN (?)', Query.categories).or(results.where('tags.name IN (?)', Query.tags))
@ -115,7 +115,7 @@ module KnowledgeExplorer
results = results.offset(offset).limit(@limit) #results[offset...page_range] results = results.offset(offset).limit(@limit) #results[offset...page_range]
# assemble the object # assemble the object
topic_query = tq.create_list(:knowledge_explorer, { unordered: true }, results) topic_query = tq.create_list(:docs, { unordered: true }, results)
topic_list = TopicListSerializer.new(topic_query, scope: Guardian.new(@user)).as_json topic_list = TopicListSerializer.new(topic_query, scope: Guardian.new(@user)).as_json

7
lib/docs_constraint.rb Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class DocsConstraint
def matches?(_request)
SiteSetting.docs_enabled
end
end

View File

@ -1,7 +0,0 @@
# frozen_string_literal: true
class KnowledgeExplorerConstraint
def matches?(_request)
SiteSetting.knowledge_explorer_enabled
end
end

View File

@ -1,31 +1,31 @@
# frozen_string_literal: true # frozen_string_literal: true
# name: discourse-knowledge-explorer # name: discourse-docs
# about: A plugin to make it easy to explore and find knowledge base-type articles in Discourse # about: A plugin to make it easy to explore and find knowledge base documents in Discourse
# version: 0.1 # version: 0.1
# author: Justin DiRose # author: Justin DiRose
# url: https://github.com/discourse/discourse-knowledge-explorer # url: https://github.com/discourse/discourse-knowledge-explorer
enabled_site_setting :knowledge_explorer_enabled enabled_site_setting :docs_enabled
register_asset 'stylesheets/common/knowledge-explorer.scss' register_asset 'stylesheets/common/docs.scss'
register_asset 'stylesheets/mobile/knowledge-explorer.scss' register_asset 'stylesheets/mobile/docs.scss'
load File.expand_path('lib/knowledge_explorer/engine.rb', __dir__) load File.expand_path('lib/docs/engine.rb', __dir__)
load File.expand_path('lib/knowledge_explorer/query.rb', __dir__) load File.expand_path('lib/docs/query.rb', __dir__)
after_initialize do after_initialize do
require_dependency 'search' require_dependency 'search'
if SiteSetting.knowledge_explorer_enabled if SiteSetting.docs_enabled
if Search.respond_to? :advanced_filter if Search.respond_to? :advanced_filter
Search.advanced_filter(/in:kb/) do |posts| Search.advanced_filter(/in:kb/) do |posts|
selected_categories = SiteSetting.knowledge_explorer_categories.split('|') selected_categories = SiteSetting.docs_categories.split('|')
if selected_categories if selected_categories
categories = Category.where('id IN (?)', selected_categories).pluck(:id) categories = Category.where('id IN (?)', selected_categories).pluck(:id)
end end
selected_tags = SiteSetting.knowledge_explorer_tags.split('|') selected_tags = SiteSetting.docs_tags.split('|')
if selected_tags if selected_tags
tags = Tag.where('name IN (?)', selected_tags).pluck(:id) tags = Tag.where('name IN (?)', selected_tags).pluck(:id)
end end
@ -34,7 +34,7 @@ after_initialize do
end end
end end
end end
add_to_class(:topic_query, :list_knowledge_explorer_topics) do add_to_class(:topic_query, :list_docs_topics) do
default_results(@options) default_results(@options)
end end
end end

View File

@ -2,7 +2,7 @@
require 'rails_helper' require 'rails_helper'
describe KnowledgeExplorer::KnowledgeExplorerController do describe Docs::DocsController do
fab!(:category) { Fabricate(:category) } fab!(:category) { Fabricate(:category) }
fab!(:topic) { Fabricate(:topic, title: "I love carrot today", category: category) } fab!(:topic) { Fabricate(:topic, title: "I love carrot today", category: category) }
fab!(:topic2) { Fabricate(:topic, title: "I love pineapple today", category: category) } fab!(:topic2) { Fabricate(:topic, title: "I love pineapple today", category: category) }
@ -10,12 +10,12 @@ describe KnowledgeExplorer::KnowledgeExplorerController do
before do before do
SiteSetting.tagging_enabled = true SiteSetting.tagging_enabled = true
SiteSetting.knowledge_explorer_enabled = true SiteSetting.docs_enabled = true
SiteSetting.knowledge_explorer_categories = category.id.to_s SiteSetting.docs_categories = category.id.to_s
SiteSetting.knowledge_explorer_tags = 'test' SiteSetting.docs_tags = 'test'
end end
describe 'knowledge explorer data' do describe 'docs data' do
context 'when any user' do context 'when any user' do
it 'should return the right response' do it 'should return the right response' do
get '/docs.json' get '/docs.json'
@ -40,13 +40,13 @@ describe KnowledgeExplorer::KnowledgeExplorerController do
end end
end end
context 'when some knowledge explorer topics are private' do context 'when some docs topics are private' do
let!(:group) { Fabricate(:group) } let!(:group) { Fabricate(:group) }
let!(:private_category) { Fabricate(:private_category, group: group) } let!(:private_category) { Fabricate(:private_category, group: group) }
let!(:private_topic) { Fabricate(:topic, category: private_category) } let!(:private_topic) { Fabricate(:topic, category: private_category) }
before do before do
SiteSetting.knowledge_explorer_categories = "#{category.id}|#{private_category.id}" SiteSetting.docs_categories = "#{category.id}|#{private_category.id}"
end end
it 'should not show topics in private categories without permissions' do it 'should not show topics in private categories without permissions' do
@ -105,7 +105,7 @@ describe KnowledgeExplorer::KnowledgeExplorerController do
let!(:topic3) { Fabricate(:topic, category: category2) } let!(:topic3) { Fabricate(:topic, category: category2) }
before do before do
SiteSetting.knowledge_explorer_categories = "#{category.id}|#{category2.id}" SiteSetting.docs_categories = "#{category.id}|#{category2.id}"
end end
it 'should return a list filtered by category' do it 'should return a list filtered by category' do
@ -230,22 +230,22 @@ describe KnowledgeExplorer::KnowledgeExplorerController do
expect(response.parsed_body['topic']['id']).to eq(topic.id) expect(response.parsed_body['topic']['id']).to eq(topic.id)
end end
it 'should get topics matching a selected knowledge explorer tag or category' do it 'should get topics matching a selected docs tag or category' do
get "/docs.json?topic=#{non_ke_topic.id}" get "/docs.json?topic=#{non_ke_topic.id}"
expect(response.parsed_body['topic']).to be_blank expect(response.parsed_body['topic']).to be_blank
end end
it 'should return a KE topic when only tags are added to settings' do it 'should return a docs topic when only tags are added to settings' do
SiteSetting.knowledge_explorer_categories = nil SiteSetting.docs_categories = nil
get "/docs.json?topic=#{topic.id}" get "/docs.json?topic=#{topic.id}"
expect(response.parsed_body['topic']['id']).to eq(topic.id) expect(response.parsed_body['topic']['id']).to eq(topic.id)
end end
it 'should return a KE topic when only categories are added to settings' do it 'should return a docs topic when only categories are added to settings' do
SiteSetting.knowledge_explorer_tags = nil SiteSetting.docs_tags = nil
get "/docs.json?topic=#{topic.id}" get "/docs.json?topic=#{topic.id}"

View File

@ -1,10 +1,10 @@
import { acceptance, queryAll } from "helpers/qunit-helpers"; import { acceptance, queryAll } from "helpers/qunit-helpers";
import docsFixtures from "../fixtures/docs"; import docsFixtures from "../fixtures/docs";
acceptance("Knowledge Explorer", function (needs) { acceptance("Docs", function (needs) {
needs.user(); needs.user();
needs.settings({ needs.settings({
knowledge_explorer_enabled: true, docs_enabled: true,
}); });
needs.pretender((server, helper) => { needs.pretender((server, helper) => {
@ -14,18 +14,12 @@ acceptance("Knowledge Explorer", function (needs) {
test("index page", async function (assert) { test("index page", async function (assert) {
await visit("/"); await visit("/");
await click("#toggle-hamburger-menu"); await click("#toggle-hamburger-menu");
await click(".knowledge-explorer-link"); await click(".docs-link");
assert.equal(queryAll(".docs-category")[0].innerText.trim(), "bug 119");
assert.equal(queryAll(".docs-tag")[0].innerText.trim(), "something 74");
assert.equal( assert.equal(
queryAll(".knowledge-explorer-category")[0].innerText.trim(), queryAll(".docs-topic-link")[0].innerText.trim(),
"bug 119"
);
assert.equal(
queryAll(".knowledge-explorer-tag")[0].innerText.trim(),
"something 74"
);
assert.equal(
queryAll(".knowledge-explorer-topic-link")[0].innerText.trim(),
"Importing from Software X" "Importing from Software X"
); );
}); });