From 4d26cf78f0f3d3abe60dc6d406aa788f0128107d Mon Sep 17 00:00:00 2001 From: Isaac Janzen <50783505+janzenisaac@users.noreply.github.com> Date: Thu, 5 Jan 2023 09:27:10 -0600 Subject: [PATCH] DEV: Upgrade `admin-plugins-explorer` to Octane (#209) - Drop `explorer-container` and move its logic to `admin-plugin-explorer` container - Convert resizing of the query edit pane from jquery -> draggable modifier --- .../discourse/components/code-view.hbs | 1 + .../components/explorer-container.js | 96 --- .../controllers/admin-plugins-explorer.js | 622 ++++++++------- assets/javascripts/discourse/models/query.js | 20 +- .../routes/admin-plugins-explorer.js | 1 - .../templates/admin/plugins-explorer.hbs | 735 +++++++++--------- .../templates/components/hljs-code-view.hbs | 1 - .../discourse/templates/modal/query-help.hbs | 4 +- config/locales/client.ar.yml | 2 +- config/locales/client.it.yml | 2 +- config/locales/client.pt_BR.yml | 2 +- config/locales/server.hr.yml | 2 +- config/locales/server.pt.yml | 2 +- config/locales/server.sk.yml | 2 +- translator.yml | 8 +- 15 files changed, 731 insertions(+), 769 deletions(-) create mode 100644 assets/javascripts/discourse/components/code-view.hbs delete mode 100644 assets/javascripts/discourse/components/explorer-container.js delete mode 100644 assets/javascripts/discourse/templates/components/hljs-code-view.hbs diff --git a/assets/javascripts/discourse/components/code-view.hbs b/assets/javascripts/discourse/components/code-view.hbs new file mode 100644 index 0000000..8761e3c --- /dev/null +++ b/assets/javascripts/discourse/components/code-view.hbs @@ -0,0 +1 @@ +
{{@value}}
\ No newline at end of file diff --git a/assets/javascripts/discourse/components/explorer-container.js b/assets/javascripts/discourse/components/explorer-container.js deleted file mode 100644 index 34c4891..0000000 --- a/assets/javascripts/discourse/components/explorer-container.js +++ /dev/null @@ -1,96 +0,0 @@ -import Component from "@ember/component"; -import { observes } from "discourse-common/utils/decorators"; -import { schedule, throttle } from "@ember/runloop"; - -export default Component.extend({ - @observes("hideSchema") - _onHideSchema() { - this.appEvents.trigger("ace:resize"); - }, - - @observes("everEditing") - _onInsertEditor() { - schedule("afterRender", this, () => this._bindControls()); - }, - - _bindControls() { - if (this._state !== "inDOM") { - return; - } - const $editPane = $(".query-editor"); - if (!$editPane.length) { - return; - } - - const oldGrippie = this.grippie; - if (oldGrippie) { - oldGrippie.off("mousedown mousemove mouseup"); - } - - const $grippie = $editPane.find(".grippie"); - const $target = $editPane.find(".panels-flex"); - const $document = $(document); - - const minWidth = $target.width(); - const minHeight = $target.height(); - - this.set("grippie", $grippie); - - const mousemove = (e) => { - const diffY = this.startY - e.screenY; - const diffX = this.startX - e.screenX; - - const newHeight = Math.max(minHeight, this.startHeight - diffY); - const newWidth = Math.max(minWidth, this.startWidth - diffX); - - $target.height(newHeight); - $target.width(newWidth); - $grippie.width(newWidth); - this.appEvents.trigger("ace:resize"); - }; - - const throttledMousemove = ((event) => { - event.preventDefault(); - throttle(this, mousemove, event, 20); - }).bind(this); - - const mouseup = (() => { - $document.off("mousemove", throttledMousemove); - $document.off("mouseup", mouseup); - this.setProperties({ - startY: null, - startX: null, - startHeight: null, - startWidth: null, - }); - }).bind(this); - - $grippie.on("mousedown", (e) => { - this.setProperties({ - startY: e.screenY, - startX: e.screenX, - startHeight: $target.height(), - startWidth: $target.width(), - }); - - $document.on("mousemove", throttledMousemove); - $document.on("mouseup", mouseup); - e.preventDefault(); - }); - }, - - didInsertElement() { - this._super(...arguments); - - this._bindControls(); - }, - - willDestroyElement() { - this._super(...arguments); - - if (this.everEditing) { - this.grippie && this.grippie.off("mousedown"); - this.set("grippie", null); - } - }, -}); diff --git a/assets/javascripts/discourse/controllers/admin-plugins-explorer.js b/assets/javascripts/discourse/controllers/admin-plugins-explorer.js index 6a5750c..eb5cf74 100644 --- a/assets/javascripts/discourse/controllers/admin-plugins-explorer.js +++ b/assets/javascripts/discourse/controllers/admin-plugins-explorer.js @@ -3,140 +3,126 @@ import showModal from "discourse/lib/show-modal"; import Query from "discourse/plugins/discourse-data-explorer/discourse/models/query"; import { popupAjaxError } from "discourse/lib/ajax-error"; import { ajax } from "discourse/lib/ajax"; -import discourseComputed, { - bind, - observes, -} from "discourse-common/utils/decorators"; +import { bind } from "discourse-common/utils/decorators"; import I18n from "I18n"; import { Promise } from "rsvp"; import { inject as service } from "@ember/service"; -import { get } from "@ember/object"; -import { not, reads, sort } from "@ember/object/computed"; +import { action } from "@ember/object"; +import { tracked } from "@glimmer/tracking"; const NoQuery = Query.create({ name: "No queries", fake: true, group_ids: [] }); -export default Controller.extend({ - dialog: service(), - queryParams: { selectedQueryId: "id", params: "params" }, - selectedQueryId: null, - editDisabled: false, - showResults: false, - hideSchema: false, - loading: false, - explain: false, +export default class PluginsExplorerController extends Controller { + @service dialog; + @service appEvents; - saveDisabled: not("selectedItem.dirty"), - runDisabled: reads("selectedItem.dirty"), - results: reads("selectedItem.results"), + @tracked sortByProperty = "last_run_at"; + @tracked sortDescending = true; + @tracked params; + @tracked search; + @tracked newQueryName; + @tracked showCreate; + @tracked editingName = false; + @tracked editingQuery = false; + @tracked selectedQueryId; + @tracked loading = false; + @tracked showResults = false; + @tracked hideSchema = false; + @tracked results = this.selectedItem.results; + @tracked dirty = false; - asc: null, - order: null, - editing: false, - everEditing: false, - showRecentQueries: true, - sortBy: ["last_run_at:desc"], - sortedQueries: sort("model", "sortBy"), + queryParams = ["params", { selectedQueryId: "id" }]; + explain = false; + acceptedImportFileTypes = ["application/json"]; + order = null; - @discourseComputed("params") - parsedParams(params) { - return params ? JSON.parse(params) : null; - }, + get validQueryPresent() { + return !!this.selectedItem.id; + } - @discourseComputed - acceptedImportFileTypes() { - return ["application/json"]; - }, + get saveDisabled() { + return !this.dirty; + } - @discourseComputed("search", "sortBy") - filteredContent(search) { - const regexp = new RegExp(search, "i"); + get runDisabled() { + return this.dirty; + } + + get sortedQueries() { + const sortedQueries = this.model.sortBy(this.sortByProperty); + return this.sortDescending ? sortedQueries.reverse() : sortedQueries; + } + + get parsedParams() { + return this.params ? JSON.parse(this.params) : null; + } + + get filteredContent() { + const regexp = new RegExp(this.search, "i"); return this.sortedQueries.filter( (result) => regexp.test(result.name) || regexp.test(result.description) ); - }, + } - @discourseComputed("newQueryName") - createDisabled(newQueryName) { - return (newQueryName || "").trim().length === 0; - }, + get createDisabled() { + return (this.newQueryName || "").trim().length === 0; + } - @discourseComputed("selectedQueryId") - selectedItem(selectedQueryId) { - const id = parseInt(selectedQueryId, 10); - const item = this.model.findBy("id", id); + get selectedItem() { + const query = this.model.findBy("id", parseInt(this.selectedQueryId, 10)); + return query || NoQuery; + } - !isNaN(id) - ? this.set("showRecentQueries", false) - : this.set("showRecentQueries", true); + get editDisabled() { + return parseInt(this.selectedQueryId, 10) < 0 ? true : false; + } - if (id < 0) { - this.set("editDisabled", true); - } - - return item || NoQuery; - }, - - @discourseComputed("selectedItem", "editing") - selectedGroupNames() { - const groupIds = this.selectedItem.group_ids || []; - const groupNames = groupIds.map((id) => { - return this.groupOptions.find((groupOption) => groupOption.id === id) - .name; - }); - return groupNames.join(", "); - }, - - @discourseComputed("groups") - groupOptions(groups) { - return groups + get groupOptions() { + return this.groups .filter((g) => g.id !== 0) .map((g) => { return { id: g.id, name: g.name }; }); - }, + } - @discourseComputed("selectedItem", "selectedItem.dirty") - othersDirty(selectedItem) { - return !!this.model.find((q) => q !== selectedItem && q.dirty); - }, - - @observes("editing") - setEverEditing() { - if (this.editing && !this.everEditing) { - this.set("everEditing", true); - } - }, + get othersDirty() { + return !!this.model.find((q) => q !== this.selectedItem && this.dirty); + } addCreatedRecord(record) { this.model.pushObject(record); - this.set("selectedQueryId", get(record, "id")); - this.selectedItem.set("dirty", false); + this.selectedQueryId = record.id; + this.dirty = false; this.setProperties({ showResults: false, results: null, - editing: true, + editingName: true, + editingQuery: true, }); - }, + } + @action save() { - this.set("loading", true); - if (this.get("selectedItem.description") === "") { - this.set("selectedItem.description", ""); - } + this.loading = true; return this.selectedItem .save() .then(() => { - const query = this.selectedItem; - query.markNotDirty(); - this.set("editing", false); + this.dirty = false; + this.editingName = false; + this.editingQuery = false; }) .catch((x) => { popupAjaxError(x); throw x; }) - .finally(() => this.set("loading", false)); - }, + .finally(() => (this.loading = false)); + } + + @action + saveAndRun() { + this.save().then(() => this.run()); + } async _importQuery(file) { const json = await this._readFileAsTextAsync(file); @@ -144,7 +130,7 @@ export default Controller.extend({ const record = this.store.createRecord("query", query); const response = await record.save(); return response.target; - }, + } _parseQuery(json) { const parsed = JSON.parse(json); @@ -154,7 +140,7 @@ export default Controller.extend({ } query.id = 0; // 0 means no Id yet return query; - }, + } _readFileAsTextAsync(file) { return new Promise((resolve, reject) => { @@ -166,200 +152,270 @@ export default Controller.extend({ reader.readAsText(file); }); - }, + } + + @bind + dragMove(e) { + if (!e.movementY && !e.movementX) { + return; + } + + const editPane = document.querySelector(".query-editor"); + const target = editPane.querySelector(".panels-flex"); + const grippie = editPane.querySelector(".grippie"); + + // we need to get the initial height / width of edit pane + // before we manipulate the size + if (!this.initialPaneWidth && !this.originalPaneHeight) { + this.originalPaneWidth = target.clientWidth; + this.originalPaneHeight = target.clientHeight; + } + + const newHeight = Math.max( + this.originalPaneHeight, + target.clientHeight + e.movementY + ); + const newWidth = Math.max( + this.originalPaneWidth, + target.clientWidth + e.movementX + ); + + target.style.height = newHeight + "px"; + target.style.width = newWidth + "px"; + grippie.style.width = newWidth + "px"; + this.appEvents.trigger("ace:resize"); + } + + @bind + didStartDrag() {} + + @bind + didEndDrag() {} @bind scrollTop() { window.scrollTo(0, 0); - this.setProperties({ editing: false, everEditing: false }); - }, + this.editingName = false; + this.editingQuery = false; + } - actions: { - updateHideSchema(value) { - this.set("hideSchema", value); - }, + @action + updateGroupIds(value) { + this.dirty = true; + this.selectedItem.set("group_ids", value); + } - import(files) { - this.set("loading", true); - const file = files[0]; - this._importQuery(file) - .then((record) => this.addCreatedRecord(record)) - .catch((e) => { - if (e.jqXHR) { - popupAjaxError(e); - } else if (e instanceof SyntaxError) { - this.dialog.alert(I18n.t("explorer.import.unparseable_json")); - } else if (e instanceof TypeError) { - this.dialog.alert(I18n.t("explorer.import.wrong_json")); - } else { - this.dialog.alert(I18n.t("errors.desc.unknown")); - // eslint-disable-next-line no-console - console.error(e); - } - }) - .finally(() => { - this.set("loading", false); - }); - }, + @action + updateHideSchema(value) { + this.hideSchema = value; + } - showCreate() { - this.set("showCreate", true); - }, - - editName() { - this.set("editing", true); - }, - - download() { - window.open(this.get("selectedItem.downloadUrl"), "_blank"); - }, - - goHome() { - this.setProperties({ - asc: null, - order: null, - showResults: false, - editDisabled: false, - showRecentQueries: true, - selectedQueryId: null, - params: null, - sortBy: ["last_run_at:desc"], - }); - this.transitionToRoute({ queryParams: { id: null, params: null } }); - }, - - showHelpModal() { - showModal("query-help"); - }, - - resetParams() { - this.selectedItem.resetParams(); - }, - - saveDefaults() { - this.selectedItem.saveDefaults(); - }, - - save() { - this.save(); - }, - - saverun() { - this.save().then(() => this.send("run")); - }, - - sortByProperty(property) { - if (this.sortBy[0] === `${property}:desc`) { - this.set("sortBy", [`${property}:asc`]); - } else { - this.set("sortBy", [`${property}:desc`]); - } - }, - - create() { - const name = this.newQueryName.trim(); - this.setProperties({ - loading: true, - showCreate: false, - showRecentQueries: false, - }); - this.store - .createRecord("query", { name }) - .save() - .then((result) => this.addCreatedRecord(result.target)) - .catch(popupAjaxError) - .finally(() => this.set("loading", false)); - }, - - discard() { - this.set("loading", true); - this.store - .find("query", this.get("selectedItem.id")) - .then((result) => { - const query = this.get("selectedItem"); - query.setProperties(result.getProperties(Query.updatePropertyNames)); - if (!query.group_ids || !Array.isArray(query.group_ids)) { - query.set("group_ids", []); - } - query.markNotDirty(); - this.set("editing", false); - }) - .catch(popupAjaxError) - .finally(() => this.set("loading", false)); - }, - - destroy() { - const query = this.selectedItem; - this.setProperties({ loading: true, showResults: false }); - this.store - .destroyRecord("query", query) - .then(() => query.set("destroyed", true)) - .catch(popupAjaxError) - .finally(() => this.set("loading", false)); - }, - - recover() { - const query = this.selectedItem; - this.setProperties({ loading: true, showResults: true }); - query - .save() - .then(() => query.set("destroyed", false)) - .catch(popupAjaxError) - .finally(() => { - this.set("loading", false); - }); - }, - - // This is necessary with glimmer's one way data stream to get the child's - // changes of 'params' to bubble up. - updateParams(identifier, value) { - this.selectedItem.set(`params.${identifier}`, value); - }, - - run() { - if (this.get("selectedItem.dirty")) { - return; - } - if (this.runDisabled) { - return; - } - - this.setProperties({ - loading: true, - showResults: false, - params: JSON.stringify(this.selectedItem.params), - }); - - ajax( - "/admin/plugins/explorer/queries/" + - this.get("selectedItem.id") + - "/run", - { - type: "POST", - data: { - params: JSON.stringify(this.get("selectedItem.params")), - explain: this.explain, - }, + @action + import(files) { + this.loading = true; + const file = files[0]; + this._importQuery(file) + .then((record) => this.addCreatedRecord(record)) + .catch((e) => { + if (e.jqXHR) { + popupAjaxError(e); + } else if (e instanceof SyntaxError) { + this.dialog.alert(I18n.t("explorer.import.unparseable_json")); + } else if (e instanceof TypeError) { + this.dialog.alert(I18n.t("explorer.import.wrong_json")); + } else { + this.dialog.alert(I18n.t("errors.desc.unknown")); + // eslint-disable-next-line no-console + console.error(e); } - ) - .then((result) => { - this.set("results", result); - if (!result.success) { - this.set("showResults", false); - return; - } + }) + .finally(() => { + this.loading = false; + this.dirty = true; + }); + } - this.set("showResults", true); - }) - .catch((err) => { - this.set("showResults", false); - if (err.jqXHR && err.jqXHR.status === 422 && err.jqXHR.responseJSON) { - this.set("results", err.jqXHR.responseJSON); - } else { - popupAjaxError(err); - } - }) - .finally(() => this.set("loading", false)); - }, - }, -}); + @action + displayCreate() { + this.showCreate = true; + } + + @action + editName() { + this.editingName = true; + } + + @action + editQuery() { + this.editingQuery = true; + } + + @action + download() { + window.open(this.selectedItem.downloadUrl, "_blank"); + } + + @action + goHome() { + this.setProperties({ + order: null, + showResults: false, + selectedQueryId: null, + params: null, + sortByProperty: "last_run_at", + sortDescending: true, + }); + this.transitionToRoute({ queryParams: { id: null, params: null } }); + } + + @action + showHelpModal() { + showModal("query-help"); + } + + @action + resetParams() { + this.selectedItem.resetParams(); + } + + @action + saveDefaults() { + this.selectedItem.saveDefaults(); + } + + @action + updateSortProperty(property) { + if (this.sortByProperty === property) { + this.sortDescending = !this.sortDescending; + } else { + this.sortByProperty = property; + this.sortDescending = true; + } + } + + @action + create() { + const name = this.newQueryName.trim(); + this.setProperties({ + loading: true, + showCreate: false, + }); + this.store + .createRecord("query", { name }) + .save() + .then((result) => this.addCreatedRecord(result.target)) + .catch(popupAjaxError) + .finally(() => { + this.loading = false; + this.dirty = true; + }); + } + + @action + discard() { + this.loading = true; + this.store + .find("query", this.selectedItem.id) + .then((result) => { + this.selectedItem.setProperties( + result.getProperties(Query.updatePropertyNames) + ); + if ( + !this.selectedItem.group_ids || + !Array.isArray(this.selectedItem.group_ids) + ) { + this.selectedItem.set("group_ids", []); + } + this.dirty = false; + this.editingName = false; + this.editingQuery = false; + }) + .catch(popupAjaxError) + .finally(() => (this.loading = false)); + } + + @action + destroyQuery() { + this.loading = true; + this.showResults = false; + this.store + .destroyRecord("query", this.selectedItem) + .then(() => this.selectedItem.set("destroyed", true)) + .catch(popupAjaxError) + .finally(() => (this.loading = false)); + } + + @action + recover() { + this.loading = true; + this.showResults = true; + this.selectedItem + .save() + .then(() => this.selectedItem.set("destroyed", false)) + .catch(popupAjaxError) + .finally(() => (this.loading = false)); + } + + @action + updateParams(identifier, value) { + this.selectedItem.set(`params.${identifier}`, value); + } + + @action + updateSearch(value) { + this.search = value; + } + + @action + updateNewQueryName(value) { + this.newQueryName = value; + } + + @action + setDirty() { + this.dirty = true; + } + + @action + exitEdit() { + this.editingName = false; + } + + @action + run() { + if (this.dirty || this.runDisabled) { + return; + } + + this.setProperties({ + loading: true, + showResults: false, + params: JSON.stringify(this.selectedItem.params), + }); + + ajax("/admin/plugins/explorer/queries/" + this.selectedItem.id + "/run", { + type: "POST", + data: { + params: JSON.stringify(this.selectedItem.params), + explain: this.explain, + }, + }) + .then((result) => { + this.results = result; + if (!result.success) { + this.showResults = false; + return; + } + this.showResults = true; + }) + .catch((err) => { + this.showResults = false; + if (err.jqXHR && err.jqXHR.status === 422 && err.jqXHR.responseJSON) { + this.results = err.jqXHR.responseJSON; + } else { + popupAjaxError(err); + } + }) + .finally(() => (this.loading = false)); + } +} diff --git a/assets/javascripts/discourse/models/query.js b/assets/javascripts/discourse/models/query.js index fbfffc8..d167ba2 100644 --- a/assets/javascripts/discourse/models/query.js +++ b/assets/javascripts/discourse/models/query.js @@ -7,16 +7,9 @@ import RestModel from "discourse/models/rest"; import { reads } from "@ember/object/computed"; const Query = RestModel.extend({ - dirty: false, params: {}, results: null, - - @on("init") - _init() { - this._super(...arguments); - - this.set("dirty", false); - }, + hasParams: reads("param_info.length"), @on("init") @observes("param_info") @@ -24,17 +17,6 @@ const Query = RestModel.extend({ this.resetParams(); }, - @observes("name", "description", "sql", "group_ids") - markDirty() { - this.set("dirty", true); - }, - - markNotDirty() { - this.set("dirty", false); - }, - - hasParams: reads("param_info.length"), - resetParams() { const newParams = {}; const oldParams = this.params; diff --git a/assets/javascripts/discourse/routes/admin-plugins-explorer.js b/assets/javascripts/discourse/routes/admin-plugins-explorer.js index f6bf357..83025e4 100644 --- a/assets/javascripts/discourse/routes/admin-plugins-explorer.js +++ b/assets/javascripts/discourse/routes/admin-plugins-explorer.js @@ -25,7 +25,6 @@ export default DiscourseRoute.extend({ return schemaPromise.then((schema) => { return queryPromise.then((model) => { model.forEach((query) => { - query.markNotDirty(); query.set( "group_names", (query.group_ids || []).map((id) => groupNames[id]) diff --git a/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs b/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs index 1c6d4b0..af7681a 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-explorer.hbs @@ -1,368 +1,389 @@ -{{#explorer-container hideSchema=hideSchema everEditing=everEditing}} - {{#if disallow}} -

{{i18n "explorer.admins_only"}}

- {{else}} - {{#unless selectedQueryId}} -
- {{text-field value=search placeholderKey="explorer.search_placeholder"}} - {{d-button - action=(action "showCreate") - icon="plus" - class="no-text btn-right" - }} - {{pick-files-button - class="import-btn" - label="explorer.import.label" - icon="upload" - acceptedFormatsOverride=acceptedImportFileTypes - showButton=true - onFilesPicked=(action "import") - }} +{{#if this.disallow}} +

{{i18n "explorer.admins_only"}}

+{{else}} + {{#unless this.validQueryPresent}} +
+ + + +
+ + {{#if this.showCreate}} +
+ + +
+ {{/if}} + + {{#if this.othersDirty}} +
+ {{d-icon "exclamation-triangle"}} + {{i18n "explorer.others_dirty"}} +
+ {{/if}} + {{/unless}} + + {{#if this.model.length}} + {{#unless this.selectedItem.fake}} +
+ {{#if this.selectedItem}} + {{#if this.editingName}} +
+ + +
+ +
+
+ +
+ +
+ {{else}} +
+ + +

+ {{this.selectedItem.name}} + {{#unless this.editDisabled}} + + {{d-icon "pencil-alt"}} + + {{/unless}} +

+
+ +
+ {{this.selectedItem.description}} +
+ {{/if}} + + {{#unless this.selectedItem.destroyed}} +
+
+ {{i18n "explorer.allow_groups"}} + + + +
+
+ {{/unless}} + +
+ + {{#if this.editingQuery}} +
+
+
+ +
+ +
+ +
+
+ +
+ {{d-icon "discourse-expand"}} +
+ +
+
+ {{else}} +
+ +
+ {{/if}} + +
+ +
+ {{#if this.editingQuery}} + + {{else}} + {{#unless this.editDisabled}} + + {{/unless}} + {{/if}} + + + + {{#if this.editingQuery}} + + {{/if}} +
+ +
+ {{#if this.selectedItem.destroyed}} + + {{else}} + {{#if this.editingQuery}} + + {{/if}} + + + {{/if}} +
+ +
+ {{/if}}
- {{#if showCreate}} -
- {{text-field - value=newQueryName - placeholderKey="explorer.create_placeholder" - }} - {{d-button - action=(action "create") - disabled=createDisabled - label="explorer.create" - icon="plus" - }} -
- {{/if}} +
+ - {{#if othersDirty}} -
- {{d-icon "exclamation-triangle"}} - {{i18n "explorer.others_dirty"}} -
- {{/if}} + {{#if this.runDisabled}} + {{#if this.saveDisabled}} + + {{else}} + + {{/if}} + {{else}} + + {{/if}} + + + +
{{/unless}} - {{#if model.length}} - {{#unless selectedItem.fake}} -
- {{#if selectedItem}} - {{#if editing}} -
- {{d-button - action=(action "goHome") - icon="chevron-left" - class="previous" - }} -
- {{text-field value=selectedItem.name}} -
-
+ -
- {{textarea - value=selectedItem.description - placeholder=(i18n "explorer.description_placeholder") - }} -
- {{else}} -
- {{d-button - action=(action "goHome") - icon="chevron-left" - class="previous" - }} + {{#unless this.selectedItem.fake}} + + {{/unless}} -

- {{selectedItem.name}} - {{#unless editDisabled}} - - {{d-icon "pencil-alt"}} + {{#unless this.validQueryPresent}} +
+ + + + + + + + + {{#each this.filteredContent as |query|}} + + + + + + {{else}} -
- {{hljs-code-view value=selectedItem.sql codeClass="sql"}} -
- {{/if}} +
+ + {{i18n "explorer.no_search_results"}} + + {{/each}} + +
+
+ +
+
+
+ +
+
+
+ {{i18n "explorer.query_groups"}} +
+
+
+ +
+
+ + {{query.name}} + {{query.description}} + + + {{#if query.username}} + + {{query.username}} - {{/unless}} - - - -
- {{selectedItem.description}} -
- {{/if}} - - {{#unless selectedItem.destroyed}} -
-
- {{i18n "explorer.allow_groups"}} - - {{multi-select - value=selectedItem.group_ids - content=groupOptions - allowAny=false - onSelect=(action (mut selectedItem.group_ids)) - }} - -
-
- {{/unless}} - -
- - {{! the SQL editor will show the first time you }} - {{#if everEditing}} -
-
-
- {{ace-editor - content=selectedItem.sql - mode="sql" - disabled=selectedItem.destroyed - }} -
- -
- -
-
- -
- {{d-icon "discourse-expand"}} -
- -
-
+ {{/if}} +
+ {{#each query.group_names as |group|}} + + {{/each}} + + {{#if query.last_run_at}} + + {{bound-date query.last_run_at}} + + {{else if query.created_at}} + + {{bound-date query.created_at}} + + {{/if}} +
+
+ {{/unless}} -
- -
- {{#if everEditing}} - {{d-button - action=(action "save") - label="explorer.save" - disabled=saveDisable - }} - {{else}} - {{#unless editDisabled}} - {{d-button - action=(action "editName") - label="explorer.edit" - icon="pencil-alt" - }} - {{/unless}} - {{/if}} - - {{d-button - action=(action "download") - label="explorer.export" - disabled=runDisabled - icon="download" - }} - - {{#if everEditing}} - {{d-button - action=(action "showHelpModal") - label="explorer.help.label" - icon="question-circle" - }} - {{/if}} -
- -
- {{#if selectedItem.destroyed}} - {{d-button - action=(action "recover") - class="" - icon="undo" - label="explorer.recover" - }} - {{else}} - {{#if everEditing}} - {{d-button - action=(action "discard") - icon="undo" - label="explorer.undo" - disabled=saveDisabled - }} - {{/if}} - - {{d-button - action=(action "destroy") - class="btn-danger" - icon="trash-alt" - label="explorer.delete" - }} - {{/if}} -
- -
- {{/if}} -

- -
- - - {{#if runDisabled}} - {{#if saveDisabled}} - {{d-button - label="explorer.run" - disabled="true" - class="btn-primary" - }} - {{else}} - {{d-button - action=(action "saverun") - icon="play" - label="explorer.saverun" - class="btn-primary" - }} - {{/if}} - {{else}} - {{d-button - action=(action "run") - icon="play" - label="explorer.run" - disabled=runDisabled - class="btn-primary" - type="submit" - }} - {{/if}} - - - - -
- {{/unless}} - - {{conditional-loading-spinner condition=loading}} - - {{#unless selectedItem.fake}} - - {{/unless}} - - {{#if showRecentQueries}} -
- - - - - - - - - {{#each filteredContent as |query|}} - - - - - - - {{else}} -
- - {{i18n "explorer.no_search_results"}} - - {{/each}} - -
-
- {{table-header-toggle - field="name" - labelKey="explorer.query_name" - order=order - asc=asc - automatic=true - }} -
-
-
- {{table-header-toggle - field="username" - labelKey="explorer.query_user" - order=order - asc=asc - automatic=true - }} -
-
-
- {{i18n "explorer.query_groups"}} -
-
-
- {{table-header-toggle - field="last_run_at" - labelKey="explorer.query_time" - order=order - asc=asc - automatic=true - }} -
-
- - {{query.name}} - {{query.description}} - - - {{#if query.username}} - - {{query.username}} - - {{/if}} - - {{#each query.group_names as |group|}} - - {{/each}} - - {{#if query.last_run_at}} - - {{bound-date query.last_run_at}} - - {{else if query.created_at}} - - {{bound-date query.created_at}} - - {{/if}} -
-
- {{/if}} - -
- {{/if}} +
{{/if}} -{{/explorer-container}} \ No newline at end of file +{{/if}} \ No newline at end of file diff --git a/assets/javascripts/discourse/templates/components/hljs-code-view.hbs b/assets/javascripts/discourse/templates/components/hljs-code-view.hbs deleted file mode 100644 index d1f6221..0000000 --- a/assets/javascripts/discourse/templates/components/hljs-code-view.hbs +++ /dev/null @@ -1 +0,0 @@ -
{{value}}
\ No newline at end of file diff --git a/assets/javascripts/discourse/templates/modal/query-help.hbs b/assets/javascripts/discourse/templates/modal/query-help.hbs index aa5306a..202f2e1 100644 --- a/assets/javascripts/discourse/templates/modal/query-help.hbs +++ b/assets/javascripts/discourse/templates/modal/query-help.hbs @@ -1,6 +1,6 @@ -{{#d-modal-body title="explorer.help.modal_title"}} + {{html-safe (i18n "explorer.help.auto_resolution")}} {{html-safe (i18n "explorer.help.custom_params")}} {{html-safe (i18n "explorer.help.default_values")}} {{html-safe (i18n "explorer.help.data_types")}} -{{/d-modal-body}} \ No newline at end of file + \ No newline at end of file diff --git a/config/locales/client.ar.yml b/config/locales/client.ar.yml index 33dfad7..8c9c8f8 100644 --- a/config/locales/client.ar.yml +++ b/config/locales/client.ar.yml @@ -22,7 +22,7 @@ ar: label: "استيراد" modal: "استيراد استعلام" unparseable_json: "ملف JSON غير قابل للتحليل" - wrong_json: "ملف JSON خاطئ. يجب أن يحتوي ملف JSON على كائن \"استعلام\"، والذي يجب أن يحتوي على الأقل على خاصية \"sql\"." + wrong_json: 'ملف JSON خاطئ. يجب أن يحتوي ملف JSON على كائن "استعلام"، والذي يجب أن يحتوي على الأقل على خاصية "sql".' help: label: "المساعدة" modal_title: "مساعدة مستكشف البيانات" diff --git a/config/locales/client.it.yml b/config/locales/client.it.yml index d118550..5acb9cc 100644 --- a/config/locales/client.it.yml +++ b/config/locales/client.it.yml @@ -22,7 +22,7 @@ it: label: "Importa" modal: "Importa una query" unparseable_json: "File JSON non analizzabile." - wrong_json: "File JSON errato. Un file JSON dovrebbe contenere un oggetto \"query\" contenente almeno una proprietà \"sql\"." + wrong_json: 'File JSON errato. Un file JSON dovrebbe contenere un oggetto "query" contenente almeno una proprietà "sql".' help: label: "Guida" modal_title: "Guida di Data Explorer" diff --git a/config/locales/client.pt_BR.yml b/config/locales/client.pt_BR.yml index ef25efb..4177360 100644 --- a/config/locales/client.pt_BR.yml +++ b/config/locales/client.pt_BR.yml @@ -22,7 +22,7 @@ pt_BR: label: "Importar" modal: "Importar Uma Consulta" unparseable_json: "Arquivo JSON não analisável" - wrong_json: "Arquivo JSON incorreto. Um arquivo JSON deve conter um objeto \"consulta\", que deve ter pelo menos a propriedade \"sql\"" + wrong_json: 'Arquivo JSON incorreto. Um arquivo JSON deve conter um objeto "consulta", que deve ter pelo menos a propriedade "sql"' help: label: "Ajuda" modal_title: "Ajuda do Explorador de Dados" diff --git a/config/locales/server.hr.yml b/config/locales/server.hr.yml index a2e7498..d85b35c 100644 --- a/config/locales/server.hr.yml +++ b/config/locales/server.hr.yml @@ -6,4 +6,4 @@ hr: site_settings: - data_explorer_enabled: "Uključi \"Data Explorer\" na /admin/plugins/explorer" + data_explorer_enabled: 'Uključi "Data Explorer" na /admin/plugins/explorer' diff --git a/config/locales/server.pt.yml b/config/locales/server.pt.yml index e35a16a..fdafab8 100644 --- a/config/locales/server.pt.yml +++ b/config/locales/server.pt.yml @@ -6,4 +6,4 @@ pt: site_settings: - data_explorer_enabled: "Ativar o «Explorador de Dados» em \"/admin/plugins/explorer\"" + data_explorer_enabled: 'Ativar o «Explorador de Dados» em "/admin/plugins/explorer"' diff --git a/config/locales/server.sk.yml b/config/locales/server.sk.yml index 4702a28..8dd6e84 100644 --- a/config/locales/server.sk.yml +++ b/config/locales/server.sk.yml @@ -6,4 +6,4 @@ sk: site_settings: - data_explorer_enabled: "Povoľ \"Data explorer\" v /admin/plugins/explorer" + data_explorer_enabled: 'Povoľ "Data explorer" v /admin/plugins/explorer' diff --git a/translator.yml b/translator.yml index 5caa8f7..bb099f8 100644 --- a/translator.yml +++ b/translator.yml @@ -1,7 +1,7 @@ # Configuration file for discourse-translator-bot files: -- source_path: config/locales/client.en.yml - destination_path: client.yml -- source_path: config/locales/server.en.yml - destination_path: server.yml + - source_path: config/locales/client.en.yml + destination_path: client.yml + - source_path: config/locales/server.en.yml + destination_path: server.yml