diff --git a/app/assets/javascripts/discourse/app/components/category-permission-row.js b/app/assets/javascripts/discourse/app/components/category-permission-row.js
new file mode 100644
index 0000000000..881f33a9ba
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/components/category-permission-row.js
@@ -0,0 +1,123 @@
+import I18n from "I18n";
+import Component from "@ember/component";
+import discourseComputed, { observes } from "discourse-common/utils/decorators";
+import PermissionType from "discourse/models/permission-type";
+import { equal, alias } from "@ember/object/computed";
+
+const EVERYONE = "everyone";
+
+export default Component.extend({
+ classNames: ["permission-row", "row-body"],
+ canCreate: equal("type", PermissionType.FULL),
+ everyonePermissionType: alias("everyonePermission.permission_type"),
+
+ @discourseComputed("type")
+ canReply(value) {
+ return (
+ value === PermissionType.CREATE_POST || value === PermissionType.FULL
+ );
+ },
+
+ @discourseComputed("type")
+ canReplyIcon() {
+ return this.canReply ? "check-square" : "far-square";
+ },
+
+ @discourseComputed("type")
+ canCreateIcon() {
+ return this.canCreate ? "check-square" : "far-square";
+ },
+
+ @discourseComputed("type")
+ replyGranted() {
+ return this.type <= PermissionType.CREATE_POST ? "reply-granted" : "";
+ },
+
+ @discourseComputed("type")
+ createGranted() {
+ return this.type === PermissionType.FULL ? "create-granted" : "";
+ },
+
+ @observes("everyonePermissionType")
+ inheritFromEveryone() {
+ if (this.group_name === EVERYONE) {
+ return;
+ }
+
+ // groups cannot have a lesser permission than "everyone"
+ if (this.everyonePermissionType < this.type) {
+ this.updatePermission(this.everyonePermissionType);
+ }
+ },
+
+ @discourseComputed("everyonePermissionType", "type")
+ replyDisabled(everyonePermissionType) {
+ if (
+ this.group_name !== EVERYONE &&
+ everyonePermissionType &&
+ everyonePermissionType <= PermissionType.CREATE_POST
+ ) {
+ return true;
+ }
+ return false;
+ },
+
+ @discourseComputed("replyDisabled")
+ replyTooltip() {
+ return this.replyDisabled
+ ? I18n.t("category.permissions.inherited")
+ : I18n.t("category.permissions.toggle_reply");
+ },
+
+ @discourseComputed("everyonePermissionType", "type")
+ createDisabled(everyonePermissionType) {
+ if (
+ this.group_name !== EVERYONE &&
+ everyonePermissionType &&
+ everyonePermissionType === PermissionType.FULL
+ ) {
+ return true;
+ }
+ return false;
+ },
+
+ @discourseComputed("createDisabled")
+ createTooltip() {
+ return this.createDisabled
+ ? I18n.t("category.permissions.inherited")
+ : I18n.t("category.permissions.toggle_full");
+ },
+
+ updatePermission(type) {
+ this.category.updatePermission(this.group_name, type);
+ },
+
+ actions: {
+ removeRow() {
+ this.category.removePermission(this.group_name);
+ },
+
+ setPermissionReply() {
+ if (this.type <= PermissionType.CREATE_POST) {
+ this.updatePermission(PermissionType.READONLY);
+ } else {
+ this.updatePermission(PermissionType.CREATE_POST);
+ }
+ },
+
+ setPermissionFull() {
+ if (
+ this.group_name !== EVERYONE &&
+ this.everyonePermissionType === PermissionType.FULL
+ ) {
+ return;
+ }
+
+ if (this.type === PermissionType.FULL) {
+ this.updatePermission(PermissionType.CREATE_POST);
+ } else {
+ this.updatePermission(PermissionType.FULL);
+ }
+ },
+ },
+});
diff --git a/app/assets/javascripts/discourse/app/components/edit-category-security.js b/app/assets/javascripts/discourse/app/components/edit-category-security.js
index a85558ff8a..cd69ba5043 100644
--- a/app/assets/javascripts/discourse/app/components/edit-category-security.js
+++ b/app/assets/javascripts/discourse/app/components/edit-category-security.js
@@ -1,78 +1,39 @@
import { buildCategoryPanel } from "discourse/components/edit-category-panel";
import PermissionType from "discourse/models/permission-type";
-import { on } from "discourse-common/utils/decorators";
+import discourseComputed from "discourse-common/utils/decorators";
+
+import { not } from "@ember/object/computed";
export default buildCategoryPanel("security", {
- editingPermissions: false,
selectedGroup: null,
- selectedPermission: null,
- showPendingGroupChangesAlert: false,
- interactedWithDropdowns: false,
+ noGroupSelected: not("selectedGroup"),
- @on("init")
- _setup() {
- this.setProperties({
- selectedGroup: this.get("category.availableGroups.firstObject"),
- selectedPermission: this.get(
- "category.availablePermissions.firstObject.id"
- ),
- });
+ @discourseComputed("category.permissions.@each.permission_type")
+ everyonePermission(permissions) {
+ return permissions.findBy("group_name", "everyone");
},
- @on("init")
- _registerValidator() {
- this.registerValidator(() => {
- if (
- !this.showPendingGroupChangesAlert &&
- this.interactedWithDropdowns &&
- this.activeTab
- ) {
- this.set("showPendingGroupChangesAlert", true);
- return true;
- }
- });
+ @discourseComputed("category.permissions.@each.permission_type")
+ everyoneGrantedFull() {
+ return (
+ this.everyonePermission &&
+ this.everyonePermission.permission_type === PermissionType.FULL
+ );
+ },
+
+ @discourseComputed("everyonePermission")
+ minimumPermission(everyonePermission) {
+ return everyonePermission
+ ? everyonePermission.permission_type
+ : PermissionType.READONLY;
},
actions: {
- onSelectGroup(selectedGroup) {
- this.setProperties({
- interactedWithDropdowns: true,
- selectedGroup,
+ onSelectGroup(group_name) {
+ this.category.addPermission({
+ group_name,
+ permission_type: this.minimumPermission,
});
},
-
- onSelectPermission(selectedPermission) {
- this.setProperties({
- interactedWithDropdowns: true,
- selectedPermission,
- });
- },
-
- editPermissions() {
- if (!this.get("category.is_special")) {
- this.set("editingPermissions", true);
- }
- },
-
- addPermission(group, id) {
- if (!this.get("category.is_special")) {
- this.category.addPermission({
- group_name: group + "",
- permission: PermissionType.create({ id: parseInt(id, 10) }),
- });
- }
-
- this.setProperties({
- selectedGroup: this.get("category.availableGroups.firstObject"),
- showPendingGroupChangesAlert: false,
- interactedWithDropdowns: false,
- });
- },
-
- removePermission(permission) {
- if (!this.get("category.is_special")) {
- this.category.removePermission(permission);
- }
- },
},
});
diff --git a/app/assets/javascripts/discourse/app/components/edit-category-tab.js b/app/assets/javascripts/discourse/app/components/edit-category-tab.js
index eb0f52c36a..0ead526caa 100644
--- a/app/assets/javascripts/discourse/app/components/edit-category-tab.js
+++ b/app/assets/javascripts/discourse/app/components/edit-category-tab.js
@@ -6,6 +6,7 @@ import { propertyEqual } from "discourse/lib/computed";
import getURL from "discourse-common/lib/get-url";
import { empty } from "@ember/object/computed";
import DiscourseURL from "discourse/lib/url";
+import { underscore } from "@ember/string";
export default Component.extend({
tagName: "li",
@@ -21,7 +22,7 @@ export default Component.extend({
@discourseComputed("tab")
title(tab) {
- return I18n.t("category." + tab.replace("-", "_"));
+ return I18n.t(`category.${underscore(tab)}`);
},
didInsertElement() {
diff --git a/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js b/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js
index 2f38469f8e..cff351a23a 100644
--- a/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js
+++ b/app/assets/javascripts/discourse/app/controllers/edit-category-tabs.js
@@ -7,6 +7,7 @@ import DiscourseURL from "discourse/lib/url";
import { readOnly } from "@ember/object/computed";
import PermissionType from "discourse/models/permission-type";
import { NotificationLevels } from "discourse/lib/notification-levels";
+import { underscore } from "@ember/string";
export default Controller.extend({
selectedTab: "general",
@@ -69,6 +70,11 @@ export default Controller.extend({
: I18n.t("category.create");
},
+ @discourseComputed("selectedTab")
+ selectedTabTitle(tab) {
+ return I18n.t(`category.${underscore(tab)}`);
+ },
+
actions: {
registerValidator(validator) {
this.validators.push(validator);
diff --git a/app/assets/javascripts/discourse/app/models/category.js b/app/assets/javascripts/discourse/app/models/category.js
index f504c9f368..b1dbd782d2 100644
--- a/app/assets/javascripts/discourse/app/models/category.js
+++ b/app/assets/javascripts/discourse/app/models/category.js
@@ -10,6 +10,8 @@ import Site from "discourse/models/site";
import User from "discourse/models/user";
import { getOwner } from "discourse-common/lib/get-owner";
+const STAFF_GROUP_NAME = "staff";
+
const Category = RestModel.extend({
permissions: null,
@@ -22,15 +24,13 @@ const Category = RestModel.extend({
this.set("availableGroups", availableGroups);
const groupPermissions = this.group_permissions;
+
if (groupPermissions) {
this.set(
"permissions",
groupPermissions.map((elem) => {
availableGroups.removeObject(elem.group_name);
- return {
- group_name: elem.group_name,
- permission: PermissionType.create({ id: elem.permission_type }),
- };
+ return elem;
})
);
}
@@ -231,7 +231,12 @@ const Category = RestModel.extend({
_permissionsForUpdate() {
const permissions = this.permissions;
let rval = {};
- permissions.forEach((p) => (rval[p.group_name] = p.permission.id));
+ if (permissions.length) {
+ permissions.forEach((p) => (rval[p.group_name] = p.permission_type));
+ } else {
+ // empty permissions => staff-only access
+ rval[STAFF_GROUP_NAME] = PermissionType.FULL;
+ }
return rval;
},
@@ -246,9 +251,20 @@ const Category = RestModel.extend({
this.availableGroups.removeObject(permission.group_name);
},
- removePermission(permission) {
- this.permissions.removeObject(permission);
- this.availableGroups.addObject(permission.group_name);
+ removePermission(group_name) {
+ const permission = this.permissions.findBy("group_name", group_name);
+ if (permission) {
+ this.permissions.removeObject(permission);
+ this.availableGroups.addObject(group_name);
+ }
+ },
+
+ updatePermission(group_name, type) {
+ this.permissions.forEach((p, i) => {
+ if (p.group_name === group_name) {
+ this.set(`permissions.${i}.permission_type`, type);
+ }
+ });
},
@discourseComputed("topics")
diff --git a/app/assets/javascripts/discourse/app/templates/components/category-permission-row.hbs b/app/assets/javascripts/discourse/app/templates/components/category-permission-row.hbs
new file mode 100644
index 0000000000..b3ac950558
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/templates/components/category-permission-row.hbs
@@ -0,0 +1,29 @@
+
+ {{group_name}}
+
+ {{d-icon "far-trash-alt"}}
+
+
+
diff --git a/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs b/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs
index 23e2981f00..e5ec4c44d1 100644
--- a/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/edit-category-general.hbs
@@ -12,14 +12,16 @@
{{i18n "category.special_warning"}}
{{/if}} {{/if}} - {{#unless category.isUncategorizedCategory}} -