FEATURE: Quick theme installs via query parameters (#12128)

This commit is contained in:
Penar Musaraj 2021-02-18 12:51:44 -05:00 committed by GitHub
parent e175e17ebb
commit 916e1d85cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 69 additions and 18 deletions

View File

@ -18,6 +18,7 @@ export default Controller.extend(ModalFunctionality, {
local: equal("selection", "local"), local: equal("selection", "local"),
remote: equal("selection", "remote"), remote: equal("selection", "remote"),
create: equal("selection", "create"), create: equal("selection", "create"),
directRepoInstall: equal("selection", "directRepoInstall"),
selection: "popular", selection: "popular",
loading: false, loading: false,
keyGenUrl: "/admin/themes/generate_key_pair", keyGenUrl: "/admin/themes/generate_key_pair",
@ -26,6 +27,7 @@ export default Controller.extend(ModalFunctionality, {
checkPrivate: match("uploadUrl", /^git/), checkPrivate: match("uploadUrl", /^git/),
localFile: null, localFile: null,
uploadUrl: null, uploadUrl: null,
uploadName: null,
advancedVisible: false, advancedVisible: false,
selectedType: alias("themesController.currentTab"), selectedType: alias("themesController.currentTab"),
component: equal("selectedType", COMPONENTS), component: equal("selectedType", COMPONENTS),
@ -136,6 +138,7 @@ export default Controller.extend(ModalFunctionality, {
uploadUrl: null, uploadUrl: null,
publicKey: null, publicKey: null,
branch: null, branch: null,
selection: "popular",
}); });
}, },
@ -189,7 +192,7 @@ export default Controller.extend(ModalFunctionality, {
options.data.append("theme", this.localFile); options.data.append("theme", this.localFile);
} }
if (this.remote || this.popular) { if (this.remote || this.popular || this.directRepoInstall) {
const duplicate = this.themesController.model.content.find((theme) => const duplicate = this.themesController.model.content.find((theme) =>
this.themeHasSameUrl(theme, this.uploadUrl) this.themeHasSameUrl(theme, this.uploadUrl)
); );

View File

@ -1,8 +1,14 @@
import Route from "@ember/routing/route"; import Route from "@ember/routing/route";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { next } from "@ember/runloop";
import { showUnassignedComponentWarning } from "admin/routes/admin-customize-themes-show"; import { showUnassignedComponentWarning } from "admin/routes/admin-customize-themes-show";
export default Route.extend({ export default Route.extend({
queryParams: {
repoUrl: null,
repoName: null,
},
model() { model() {
return this.store.findAll("theme"); return this.store.findAll("theme");
}, },
@ -10,6 +16,18 @@ export default Route.extend({
setupController(controller, model) { setupController(controller, model) {
this._super(controller, model); this._super(controller, model);
controller.set("editingTheme", false); controller.set("editingTheme", false);
if (controller.repoUrl) {
next(() => {
showModal("admin-install-theme", {
admin: true,
}).setProperties({
uploadUrl: controller.repoUrl,
uploadName: controller.repoName,
selection: "directRepoInstall",
});
});
}
}, },
actions: { actions: {
@ -30,7 +48,12 @@ export default Route.extend({
addTheme(theme) { addTheme(theme) {
this.refresh(); this.refresh();
theme.setProperties({ recentlyInstalled: true }); theme.setProperties({ recentlyInstalled: true });
this.transitionTo("adminCustomizeThemes.show", theme.get("id")); this.transitionTo("adminCustomizeThemes.show", theme.get("id"), {
queryParams: {
repoName: null,
repoUrl: null,
},
});
}, },
}, },
}); });

View File

@ -1,10 +1,12 @@
{{#d-modal-body class="upload-selector install-theme" title="admin.customize.theme.install"}} {{#d-modal-body class="upload-selector install-theme" title="admin.customize.theme.install"}}
{{#unless directRepoInstall}}
<div class="install-theme-items"> <div class="install-theme-items">
{{install-theme-item value="popular" selection=selection label="admin.customize.theme.install_popular"}} {{install-theme-item value="popular" selection=selection label="admin.customize.theme.install_popular"}}
{{install-theme-item value="local" selection=selection label="admin.customize.theme.install_upload"}} {{install-theme-item value="local" selection=selection label="admin.customize.theme.install_upload"}}
{{install-theme-item value="remote" selection=selection label="admin.customize.theme.install_git_repo"}} {{install-theme-item value="remote" selection=selection label="admin.customize.theme.install_git_repo"}}
{{install-theme-item value="create" selection=selection label="admin.customize.theme.install_create" showIcon=true}} {{install-theme-item value="create" selection=selection label="admin.customize.theme.install_create" showIcon=true}}
</div> </div>
{{/unless}}
<div class="install-theme-content"> <div class="install-theme-content">
{{#if popular}} {{#if popular}}
<div class="popular-theme-items"> <div class="popular-theme-items">
@ -97,6 +99,13 @@
}} }}
</div> </div>
{{/if}} {{/if}}
{{#if directRepoInstall}}
<div class="repo">
<div class="label">{{html-safe (i18n "admin.customize.theme.direct_install_tip" name=uploadName)}}</div>
<pre><code>{{uploadUrl}}</code></pre>
</div>
{{/if}}
</div> </div>
{{/d-modal-body}} {{/d-modal-body}}

View File

@ -1,4 +1,4 @@
import { acceptance, queryAll } from "discourse/tests/helpers/qunit-helpers"; import { acceptance, query } from "discourse/tests/helpers/qunit-helpers";
import { click, fillIn, visit } from "@ember/test-helpers"; import { click, fillIn, visit } from "@ember/test-helpers";
import { test } from "qunit"; import { test } from "qunit";
@ -18,13 +18,14 @@ acceptance("Admin - Themes - Install modal", function (needs) {
await click(".install-theme-content .inputs .advanced-repo"); await click(".install-theme-content .inputs .advanced-repo");
await fillIn(branchInput, "tests-passed"); await fillIn(branchInput, "tests-passed");
await click(privateRepoCheckbox); await click(privateRepoCheckbox);
assert.ok(queryAll(urlInput)[0].value === themeUrl, "url input is filled"); assert.equal(query(urlInput).value, themeUrl, "url input is filled");
assert.ok( assert.equal(
queryAll(branchInput)[0].value === "tests-passed", query(branchInput).value,
"tests-passed",
"branch input is filled" "branch input is filled"
); );
assert.ok( assert.ok(
queryAll(privateRepoCheckbox)[0].checked, query(privateRepoCheckbox).checked,
"private repo checkbox is checked" "private repo checkbox is checked"
); );
@ -32,11 +33,21 @@ acceptance("Admin - Themes - Install modal", function (needs) {
await click(".create-actions .btn-primary"); await click(".create-actions .btn-primary");
await click("#remote"); await click("#remote");
assert.ok(queryAll(urlInput)[0].value === "", "url input is reset"); assert.equal(query(urlInput).value, "", "url input is reset");
assert.ok(queryAll(branchInput)[0].value === "", "branch input is reset"); assert.equal(query(branchInput).value, "", "branch input is reset");
assert.ok( assert.ok(
!queryAll(privateRepoCheckbox)[0].checked, !query(privateRepoCheckbox).checked,
"private repo checkbox unchecked" "private repo checkbox unchecked"
); );
}); });
test("modal can be auto-opened with the right query params", async function (assert) {
await visit("/admin/customize/themes?repoUrl=testUrl&repoName=testName");
assert.ok(query(".admin-install-theme-modal"), "modal is visible");
assert.equal(
query(".install-theme code").textContent.trim(),
"testUrl",
"repo url is visible"
);
});
}); });

View File

@ -62,14 +62,18 @@
} }
.install-theme-content { .install-theme-content {
padding: 0px 0px 10px 20px; width: calc(100% - 20px);
width: calc(100% - 200px);
input[type="file"] { input[type="file"] {
width: 100%; width: 100%;
overflow: hidden; // Chrome needs this overflow: hidden; // Chrome needs this
} }
} }
.install-theme-items + .install-theme-content {
padding: 0px 0px 10px 20px;
width: calc(100% - 200px);
}
.repo { .repo {
input[type="text"] { input[type="text"] {
width: 90%; width: 90%;

View File

@ -4190,6 +4190,7 @@ en:
included_components: "Included components" included_components: "Included components"
add_all: "Add all" add_all: "Add all"
import_web_tip: "Repository containing theme" import_web_tip: "Repository containing theme"
direct_install_tip: "Are you sure you want to install <strong>%{name}</strong> from the repository listed below?"
import_web_advanced: "Advanced..." import_web_advanced: "Advanced..."
import_file_tip: ".tar.gz, .zip, or .dcstyle.json file containing theme" import_file_tip: ".tar.gz, .zip, or .dcstyle.json file containing theme"
is_private: "Theme is in a private git repository" is_private: "Theme is in a private git repository"