UX: new layout for groups page, allow changes to automatic group bio (#7350)

This commit is contained in:
Maja Komel 2019-04-18 04:44:30 +02:00 committed by Kris
parent bf712a8598
commit 1f17d52f55
11 changed files with 198 additions and 285 deletions

View File

@ -21,6 +21,8 @@ export default Ember.Component.extend({
}
},
canEdit: Ember.computed.not("model.automatic"),
@computed("basicNameValidation", "uniqueNameValidation")
nameValidation(basicNameValidation, uniqueNameValidation) {
return uniqueNameValidation ? uniqueNameValidation : basicNameValidation;

View File

@ -6,19 +6,16 @@ export default Ember.Controller.extend({
@computed("model.automatic")
tabs(automatic) {
const defaultTabs = [
{ route: "group.manage.profile", title: "groups.manage.profile.title" },
{
route: "group.manage.interaction",
title: "groups.manage.interaction.title"
},
{ route: "group.manage.logs", title: "groups.manage.logs.title" }
];
if (!automatic) {
defaultTabs.splice(0, 0, {
route: "group.manage.profile",
title: "groups.manage.profile.title"
});
defaultTabs.splice(1, 0, {
route: "group.manage.membership",
title: "groups.manage.membership.title"

View File

@ -3,11 +3,5 @@ export default Discourse.Route.extend({
titleToken() {
return I18n.t("groups.manage.profile.title");
},
afterModel(group) {
if (group.get("automatic")) {
this.replaceWith("group.manage.interaction", group);
}
}
});

View File

@ -16,4 +16,6 @@
disabled=loading
icon="user-plus"
label="groups.request"}}
{{else}}
{{yield}}
{{/if}}

View File

@ -1,36 +1,38 @@
{{#if this.currentUser.admin}}
<div class="control-group">
<label class="control-label" for="name">{{i18n 'groups.name'}}</label>
{{#if canEdit}}
{{#if this.currentUser.admin}}
<div class="control-group">
<label class="control-label" for="name">{{i18n 'groups.name'}}</label>
{{text-field name="name"
class="input-xxlarge group-form-name"
value=nameInput
placeholderKey="admin.groups.name_placeholder"}}
{{text-field name="name"
class="input-xxlarge group-form-name"
value=nameInput
placeholderKey="admin.groups.name_placeholder"}}
{{input-tip validation=nameValidation}}
</div>
{{/if}}
<div class="control-group">
<label class="control-label" for='full_name'>{{i18n 'groups.manage.full_name'}}</label>
{{text-field name='full_name'
class="input-xxlarge group-form-full-name"
value=model.full_name}}
</div>
{{#if this.currentUser.admin}}
<div class="control-group">
<label class="control-label" for="title">
{{i18n 'admin.groups.default_title'}}
</label>
{{input value=model.title name="title" class="input-xxlarge"}}
<div class="control-instructions">
{{i18n 'admin.groups.default_title_description'}}
{{input-tip validation=nameValidation}}
</div>
{{/if}}
<div class="control-group">
<label class="control-label" for='full_name'>{{i18n 'groups.manage.full_name'}}</label>
{{text-field name='full_name'
class="input-xxlarge group-form-full-name"
value=model.full_name}}
</div>
{{#if this.currentUser.admin}}
<div class="control-group">
<label class="control-label" for="title">
{{i18n 'admin.groups.default_title'}}
</label>
{{input value=model.title name="title" class="input-xxlarge"}}
<div class="control-instructions">
{{i18n 'admin.groups.default_title_description'}}
</div>
</div>
{{/if}}
{{/if}}
<div class="control-group">
@ -38,10 +40,12 @@
{{d-editor value=model.bio_raw class="group-form-bio input-xxlarge"}}
</div>
{{yield}}
{{#if canEdit}}
{{yield}}
<div class="control-group">
{{group-flair-inputs model=model}}
</div>
<div class="control-group">
{{group-flair-inputs model=model}}
</div>
{{plugin-outlet name="group-edit" args=(hash group=model)}}
{{plugin-outlet name="group-edit" args=(hash group=model)}}
{{/if}}

View File

@ -1,11 +1,5 @@
<span class='groups-info-name'>{{group.displayName}}</span>
{{#if showFullName}}
<span class='groups-info-full-name'>{{group.full_name}}</span>
{{/if}}
{{#if group.title}}
<div>
<span class='groups-info-title'>{{group.title}}</span>
</div>
<span class='groups-info-name'>{{group.full_name}}</span>
{{else}}
<span class='groups-info-name'>{{group.displayName}}</span>
{{/if}}

View File

@ -25,69 +25,61 @@
{{#conditional-loading-spinner condition=model.loading}}
{{#load-more selector=".groups-table .groups-table-row" action=(action "loadMore")}}
<div class='container'>
<table class="groups-table">
<thead>
<tr>
{{directory-toggle field="name" labelKey="groups.group_name" order=order asc=asc}}
{{directory-toggle field="user_count" labelKey="groups.user_count" order=order asc=asc}}
<th>{{i18n "groups.index.group_type"}}</th>
<th>{{i18n "groups.membership"}}</th>
</tr>
</thead>
<tbody>
{{#each model as |group|}}
<tr class="groups-table-row">
<td class="groups-info">
{{#link-to "group.members" group.name}}
{{#if group.flair_url}}
<span class='group-avatar-flair'>
{{avatar-flair
flairURL=group.flair_url
flairBgColor=group.flair_bg_color
flairColor=group.flair_color
groupName=group.name}}
</span>
{{/if}}
{{groups-info group=group}}
{{/link-to}}
</td>
<td class="groups-user-count">{{d-icon "group"}}{{group.user_count}}</td>
<td class="groups-table-type">
{{#if group.public_admission}}
{{i18n 'groups.index.public'}}
{{else if group.isPrivate}}
{{d-icon "far-eye-slash"}}
{{i18n 'groups.index.private'}}
{{else}}
{{#if group.automatic}}
{{i18n 'groups.index.automatic'}}
{{else}}
{{i18n 'groups.index.closed'}}
{{/if}}
<div class="groups-boxes">
{{#each model as |group|}}
{{#link-to "group.members" group.name class="group-box"}}
<div class="group-box-inner">
<div class="group-info-wrapper">
{{#if group.flair_url}}
<span class='group-avatar-flair'>
{{avatar-flair
flairURL=group.flair_url
flairBgColor=group.flair_bg_color
flairColor=group.flair_color
groupName=group.name}}
</span>
{{/if}}
</td>
<span class="group-info">
{{groups-info group=group}}
<td class="groups-table-membership">
{{#if group.is_group_owner}}
<span>
<div class="group-user-count">{{d-icon "user"}}{{group.user_count}}</div>
</span>
</div>
<div class="group-description">{{{group.bio_excerpt}}}</div>
<div class="group-membership">
{{#group-membership-button tagName='' model=group showLogin=(route-action "showLogin")}}
{{#if group.is_group_owner}}
<span class="is-group-owner">
{{d-icon "shield"}}
{{i18n "groups.index.is_group_owner"}}
</span>
{{else if group.is_group_user}}
<span>
{{else if group.is_group_user}}
<span class="is-group-member">
{{d-icon "check"}}
{{i18n "groups.index.is_group_user"}}
</span>
{{/if}}
{{group-membership-button tagName='' model=group showLogin=(route-action "showLogin")}}
</td>
</tr>
{{/each}}
</tbody>
</table>
{{else if group.public_admission}}
{{i18n 'groups.index.public'}}
{{else if group.isPrivate}}
{{d-icon "far-eye-slash"}}
{{i18n 'groups.index.private'}}
{{else}}
{{#if group.automatic}}
{{i18n 'groups.index.automatic'}}
{{else}}
{{d-icon "ban"}}
{{i18n 'groups.index.closed'}}
{{/if}}
{{/if}}
{{/group-membership-button}}
</div>
</div>
{{/link-to}}
{{/each}}
</div>
</div>
{{/load-more}}

View File

@ -1,7 +1,7 @@
.groups-header {
display: flex;
flex-wrap: wrap;
margin-bottom: 30px;
margin-bottom: 1em;
.groups-header-new {
order: 2;
margin-bottom: 0.5em;
@ -23,206 +23,128 @@
}
}
.groups-table {
.groups-boxes {
margin: 1em 0;
width: 100%;
// IE11 falls back to flexbox
display: flex;
flex-wrap: wrap;
justify-content: space-between;
// Everything that's not IE11 uses grid
@supports (display: grid) {
display: grid;
grid-template-columns: repeat(4, 24%);
grid-column-gap: 1.333%;
grid-row-gap: 1em;
@include breakpoint("tablet") {
grid-template-columns: repeat(3, 32%);
grid-column-gap: 2%;
}
@include breakpoint("mobile") {
grid-template-columns: 100%;
}
}
tr {
td {
padding: 0.8em;
.group-box {
// Flex and margin are for IE11
flex: 1 1 24%;
margin: 1%;
@include breakpoint("mobile") {
margin: 0;
}
display: flex;
box-sizing: border-box;
cursor: pointer;
border: 1px solid $primary-low;
color: $primary;
.discourse-no-touch & {
transition: all 0.25s;
&:hover {
box-shadow: shadow("card");
}
}
.group-membership {
color: $primary-medium;
}
td.groups-info {
width: 50%;
}
td.group-user-status {
.d-icon {
color: $primary;
margin-top: auto;
padding-top: 1em;
.is-group-owner,
.is-group-member {
color: $success;
}
}
td.groups-user-count {
width: 17%;
font-size: $font-up-2;
.d-icon {
display: none;
}
}
td.groups-table-type {
width: 17%;
font-size: $font-up-1;
}
td.groups-table-membership {
font-size: $font-up-1;
.group-membership-button {
font-size: $font-down-1;
display: inline-block;
margin-left: 5px;
&:empty {
display: none;
}
}
}
@include breakpoint(mobile) {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
padding: 10px 0;
td.groups-info,
td.groups-user-count,
td.groups-table-type,
td.groups-table-membership {
width: 100%;
padding: 0;
text-align: right;
font-size: $font-0;
}
td.groups-info {
grid-column-start: 1;
grid-column-end: 4;
grid-row-start: 1;
grid-row-end: 3;
text-align: left;
line-height: $line-height-medium;
margin-bottom: 0.5em;
a {
display: flex;
}
.group-box-inner {
padding: 1em;
width: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
.group-info-wrapper {
display: flex;
overflow: hidden;
flex: 0 1 auto;
.group-avatar-flair {
margin-right: 0.5em;
margin-top: 0.3em;
margin-right: 8px;
flex: 0 0 auto;
}
.groups-info-name {
word-break: break-all;
max-width: 45vw;
}
.groups-info-full-name {
font-size: $font-down-1;
.group-info {
flex: 1 0 auto;
margin-bottom: 1em;
width: 70%;
span {
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
td.groups-user-count {
.group-user-count {
display: flex;
align-items: center;
grid-column-start: 4;
grid-row-start: 1;
.d-icon {
display: inline-block;
margin-right: 0.25em;
color: $primary-low-mid;
}
}
td.groups-table-type {
grid-row-start: 3;
grid-column-start: 1;
grid-column-end: 3;
text-align: left;
align-self: center;
color: $primary-high;
.d-icon {
margin-right: 0.25em;
font-size: 0.8em;
color: $primary-medium;
}
}
td.groups-table-membership {
grid-row-start: 3;
grid-column-start: 3;
grid-column-end: 5;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-end;
button {
margin-left: 5px;
display: flex;
}
&:empty {
display: none;
}
.group-description {
color: $primary-high;
word-wrap: break-word;
}
// IE11 grid support
display: -ms-grid;
-ms-grid-columns: 1fr 1fr;
-ms-grid-rows: 1fr 1fr;
td.groups-info {
display: -ms-grid;
-ms-grid-row: 1;
-ms-grid-column: 1;
}
td.groups-user-count {
justify-content: flex-end;
-ms-grid-row: 1;
-ms-grid-column: 2;
}
td.groups-table-type {
display: flex;
align-items: center;
-ms-grid-row: 2;
-ms-grid-column: 1;
}
td.groups-table-membership {
display: flex;
-ms-grid-row: 2;
-ms-grid-column: 2;
}
}
}
@include breakpoint(mobile) {
thead {
display: none;
}
}
.groups-info {
.group-info-details {
vertical-align: middle;
}
.groups-info-name {
font-size: $font-up-1;
font-weight: bold;
color: $primary;
color: dark-light-choose($primary-high, $secondary-low);
}
.groups-info-full-name {
color: dark-light-choose($primary-high, $secondary-low);
}
.groups-info-title {
font-size: $font-down-1;
color: dark-light-choose($primary-medium, $secondary-medium);
}
.group-avatar-flair {
vertical-align: middle;
color: $primary;
}
span {
display: inline-block;
}
$size: 40px;
$icon-size: $size / 1.8;
.avatar-flair {
background-size: $size;
height: $size;
width: $size;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-repeat: no-repeat;
.group-avatar-flair {
display: inline-block;
color: $primary;
.d-icon {
height: $icon-size;
width: $icon-size;
.avatar-flair {
background-size: $size;
height: $size;
width: $size;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
background-repeat: no-repeat;
.d-icon {
height: $icon-size;
width: $icon-size;
}
}
}
.avatar-flair-image {
width: $size;
}

View File

@ -507,6 +507,7 @@ class GroupsController < ApplicationController
mentionable_level
messageable_level
default_notification_level
bio_raw
}
else
default_params = %i{

View File

@ -19,6 +19,7 @@ class BasicGroupSerializer < ApplicationSerializer
:flair_color,
:bio_raw,
:bio_cooked,
:bio_excerpt,
:public_admission,
:public_exit,
:allow_membership_requests,
@ -38,6 +39,10 @@ class BasicGroupSerializer < ApplicationSerializer
end
end
def bio_excerpt
PrettyText.excerpt(object.bio_cooked, 110) if object.bio_cooked.present?
end
def include_incoming_email?
staff?
end

View File

@ -5,11 +5,11 @@ acceptance("Groups");
QUnit.test("Browsing Groups", async assert => {
await visit("/g?username=eviltrout");
assert.equal(count(".groups-table-row"), 1, "it displays user's groups");
assert.equal(count(".group-box"), 1, "it displays user's groups");
await visit("/g");
assert.equal(count(".groups-table-row"), 2, "it displays visible groups");
assert.equal(count(".group-box"), 2, "it displays visible groups");
assert.equal(
find(".group-index-join").length,
1,