MOBILE-3205 forum: Discussion and post new architecture

main
Pau Ferrer Ocaña 2019-10-24 13:16:53 +02:00
parent 122bd8bbe8
commit c823efe5e4
4 changed files with 171 additions and 62 deletions

View File

@ -43,51 +43,52 @@
</div>
<ng-container *ngFor="let discussion of offlineDiscussions">
<ion-item text-wrap (click)="openNewDiscussion(discussion.timecreated)" [attr.no-lines]="discussion.groupname" [class.core-split-item-selected]="discussion.timecreated == -selectedDiscussion">
<ion-avatar core-user-avatar [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
<h2><core-format-text [text]="discussion.subject" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></h2>
<h3 *ngIf="discussion.userfullname">
<ion-note float-end padding-left><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note>
{{discussion.userfullname}}
</h3>
</ion-item>
<ion-item *ngIf="discussion.groupname" (click)="openNewDiscussion(discussion.timecreated)" [class.core-split-item-selected]="discussion.timecreated == -selectedDiscussion">
<ion-note text-end>
<ion-icon name="people"></ion-icon> {{ discussion.groupname }}
</ion-note>
<ion-item text-wrap (click)="openNewDiscussion(discussion.timecreated)" [attr.no-lines]="discussion.groupname" [class.core-split-item-selected]="discussion.timecreated == -selectedDiscussion" class="addon-mod-forum-discussion">
<div class="addon-mod-forum-discussion-title">
<h2>
<core-format-text [text]="discussion.subject" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text>
</h2>
</div>
<div class="addon-mod-forum-discussion-info">
<ion-avatar core-user-avatar [user]="discussion" item-start [courseId]="courseId" *ngIf="discussion.userfullname"></ion-avatar>
<h3 *ngIf="discussion.userfullname">{{discussion.userfullname}}</h3>
<p *ngIf="discussion.groupname"><ion-icon name="people"></ion-icon> {{ discussion.groupname }}</p>
<p><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</p>
</div>
</ion-item>
</ng-container>
<ng-container *ngFor="let discussion of discussions">
<ion-item text-wrap (click)="openDiscussion(discussion)" no-lines [class.core-split-item-selected]="discussion.discussion == selectedDiscussion">
<ion-avatar core-user-avatar [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
<h2>
<core-icon name="fa-map-pin" *ngIf="discussion.pinned"></core-icon>
<core-icon name="fa-star" class="addon-forum-star" *ngIf="!discussion.pinned && discussion.starred"></core-icon>
<core-format-text [text]="discussion.subject" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text>
</h2>
<h3>
<ion-note float-end padding-left text-end>
<div *ngIf="discussion.numunread"><core-icon name="fa-circle" color="primary"></core-icon> {{ 'addon.mod_forum.unreadpostsnumber' | translate:{ '$a' : discussion.numunread} }}</div>
</ion-note>
{{discussion.userfullname}}
</h3>
<p>{{discussion.created | coreDateDayOrTime}}</p>
</ion-item>
<ion-item (click)="openDiscussion(discussion)" [class.core-split-item-selected]="discussion.discussion == selectedDiscussion">
<ion-row text-center>
<ion-col *ngIf="discussion.groupname">
<ion-item (click)="openDiscussion(discussion)" [class.core-split-item-selected]="discussion.discussion == selectedDiscussion" class="addon-mod-forum-discussion">
<div class="addon-mod-forum-discussion-title">
<h2 text-wrap>
<core-icon name="fa-map-pin" *ngIf="discussion.pinned"></core-icon>
<core-icon name="fa-star" class="addon-forum-star" *ngIf="!discussion.pinned && discussion.starred"></core-icon>
<core-format-text [text]="discussion.subject" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text>
</h2>
<button ion-button icon-only clear color="dark" (click)="showOptionsMenu($event, discussion)">
<core-icon name="more"></core-icon>
</button>
</div>
<div class="addon-mod-forum-discussion-info">
<ion-avatar core-user-avatar [user]="discussion" item-start [courseId]="courseId"></ion-avatar>
<div class="addon-mod-forum-discussion-author">
<h3>{{discussion.userfullname}}</h3>
<p *ngIf="discussion.groupname"><ion-icon name="people"></ion-icon> {{ discussion.groupname }}</p>
<p>{{discussion.created | coreFormatDate: "strftimedatetimeshort"}}</p>
</div>
</div>
<ion-row text-center class="addon-mod-forum-discussion-more-info">
<ion-col>
<ion-note>
<ion-icon name="people"></ion-icon> {{ discussion.groupname }}
<ion-icon name="time"></ion-icon> {{ 'addon.mod_forum.lastpost' | translate }}
<ng-container *ngIf="discussion.timemodified > discussion.created">{{discussion.timemodified | coreTimeAgo}}</ng-container>
<ng-container *ngIf="discussion.timemodified <= discussion.created">{{discussion.created | coreTimeAgo}}</ng-container>
</ion-note>
</ion-col>
<ion-col>
<ion-note>
<ion-icon name="chatboxes"></ion-icon> {{ 'addon.mod_forum.numreplies' | translate:{numreplies: discussion.numreplies} }}
</ion-note>
</ion-col>
<ion-col *ngIf="discussion.timemodified > discussion.created">
<ion-note>
<ion-icon name="time"></ion-icon> {{ 'addon.mod_forum.lastpost' | translate }} {{discussion.timemodified | coreTimeAgo}}
<ion-badge text-center *ngIf="discussion.numunread" [attr.aria-label]="'addon.mod_forum.unreadpostsnumber' | translate:{ '$a' : discussion.numunread}">{{ discussion.numunread }}</ion-badge>
</ion-note>
</ion-col>
</ion-row>

View File

@ -1,5 +1,54 @@
$addon-forum-avatar-size: 28px;
ion-app.app-root addon-mod-forum-index {
.addon-forum-star {
color: $core-star-color;
}
.addon-mod-forum-discussion.item {
.label {
margin-top: 4px;
h2 {
margin-top: 8px;
margin-bottom: 8px;
font-weight: bold;
ion-icon {
@include margin(0, 6px, 0, 0);
}
}
h3 {
font-size: 1.6rem;
}
}
ion-avatar {
width: $addon-forum-avatar-size;
height: $addon-forum-avatar-size;
min-width: $addon-forum-avatar-size;
min-height: $addon-forum-avatar-size;
&[item-start] {
@include margin(0, 8px, 0, 0);
}
img {
width: $addon-forum-avatar-size;
height: $addon-forum-avatar-size;
}
}
.addon-mod-forum-discussion-title,
.addon-mod-forum-discussion-info {
display: flex;
align-items: center;
}
.addon-mod-forum-discussion-title h2,
.addon-mod-forum-discussion-info .addon-mod-forum-discussion-author {
flex-grow: 1;
}
.addon-mod-forum-discussion-more-info {
font-size: 1.4rem;
clear: both;
}
}
}

View File

@ -1,22 +1,30 @@
<ion-card-header text-wrap no-padding id="addon-mod_forum-post-{{post.id}}">
<ion-item text-wrap>
<ion-avatar core-user-avatar [user]="post" item-start></ion-avatar>
<h2>
<core-icon name="fa-map-pin" *ngIf="post.parent == 0 && post.pinned"></core-icon>
<core-icon name="fa-star" class="addon-forum-star" *ngIf="post.parent == 0 && !post.pinned && post.starred"></core-icon>
<span [class.core-bold]="post.parent == 0"><core-format-text [text]="post.subject" contextLevel="module" [contextInstanceId]="forum && forum.cmid" [courseId]="courseId"></core-format-text></span>
</h2>
<p>
<ion-note float-end padding-left *ngIf="!post.modified"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</ion-note>
<ion-note float-end padding-left text-end *ngIf="post.modified">
{{post.modified | coreDateDayOrTime}}
<div *ngIf="trackPosts && !post.postread"><core-icon name="fa-circle" color="primary"></core-icon> {{ 'addon.mod_forum.unread' | translate }}</div>
</ion-note>
{{post.userfullname}}
</p>
<div class="addon-mod-forum-post-title">
<h2 text-wrap>
<core-icon name="fa-map-pin" *ngIf="post.parent == 0 && post.pinned"></core-icon>
<core-icon name="fa-star" class="addon-forum-star" *ngIf="post.parent == 0 && !post.pinned && post.starred"></core-icon>
<core-format-text [text]="post.subject" contextLevel="module" [contextInstanceId]="forum && forum.cmid" [courseId]="courseId"></core-format-text>
</h2>
<ion-badge float-end padding-left text-end *ngIf="trackPosts && !post.postread" [attr.aria-label]="'addon.mod_forum.unread' | translate">
<core-icon name="fa-circle" color="primary"></core-icon>
</ion-badge>
<button ion-button icon-only clear color="dark" (click)="showCourseOptionsMenu($event)">
<core-icon name="more"></core-icon>
</button>
</div>
<div class="addon-mod-forum-post-info">
<ion-avatar core-user-avatar [user]="post" item-start [courseId]="courseId"></ion-avatar>
<div class="addon-mod-forum-post-author">
<h3>{{post.userfullname}}</h3>
<p *ngIf="post.groupname"><ion-icon name="people"></ion-icon> {{ post.groupname }}</p>
<p *ngIf="post.modified">{{post.modified | coreFormatDate: "strftimedatetimeshort"}}</p>
<p *ngIf="!post.modified"><ion-icon name="time"></ion-icon> {{ 'core.notsent' | translate }}</p>
</div>
</div>
</ion-item>
</ion-card-header>
<ion-card-content padding-top>
<ion-card-content [attr.padding-top]="post.parent == 0 || null">
<div padding-bottom *ngIf="post.isprivatereply">
<ion-note>{{ 'addon.mod_forum.postisprivatereply' | translate }}</ion-note>
</div>
@ -30,22 +38,26 @@
</ng-container>
</div>
</ion-card-content>
<ion-item text-wrap *ngIf="tagsEnabled && post.tags && post.tags.length > 0">
<div item-start>{{ 'core.tag.tags' | translate }}:</div>
<core-tag-list [tags]="post.tags"></core-tag-list>
</ion-item>
<core-rating-rate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [itemSetId]="discussionId" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale" [userId]="post.userid" (onUpdate)="ratingUpdated()"></core-rating-rate>
<core-rating-aggregate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale"></core-rating-aggregate>
<ion-item no-padding text-end *ngIf="post.id && post.canreply && !post.isprivatereply" class="addon-forum-reply-button">
<button ion-button icon-left clear small (click)="showReply()" [attr.aria-controls]="'addon-forum-reply-edit-form-' + uniqueId" [attr.aria-expanded]="replyData.replyingTo === post.id">
<ion-icon name="undo"></ion-icon> {{ 'addon.mod_forum.reply' | translate }}
</button>
</ion-item>
<div class="addon-mod-forum-post-more-info">
<ion-item text-wrap *ngIf="tagsEnabled && post.tags && post.tags.length > 0">
<div item-start>{{ 'core.tag.tags' | translate }}:</div>
<core-tag-list [tags]="post.tags"></core-tag-list>
</ion-item>
<core-rating-rate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [itemSetId]="discussionId" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale" [userId]="post.userid" (onUpdate)="ratingUpdated()"></core-rating-rate>
<core-rating-aggregate *ngIf="forum && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale"></core-rating-aggregate>
<ion-item no-padding text-end *ngIf="post.id && post.canreply && !post.isprivatereply" class="addon-forum-reply-button">
<button ion-button icon-left clear small (click)="showReply()" [attr.aria-controls]="'addon-forum-reply-edit-form-' + uniqueId" [attr.aria-expanded]="replyData.replyingTo === post.id">
<ion-icon name="undo"></ion-icon> {{ 'addon.mod_forum.reply' | translate }}
</button>
</ion-item>
</div>
<ion-item text-end *ngIf="!post.id && (!replyData.isEditing || replyData.replyingTo != post.parent)">
<button ion-button icon-left clear small (click)="editReply()" [attr.aria-controls]="'addon-forum-reply-edit-form-' + uniqueId" [attr.aria-expanded]="replyData.replyingTo === post.parent">
<ion-icon name="create"></ion-icon> {{ 'addon.mod_forum.edit' | translate }}
</button>
</ion-item>
<ion-list [id]="'addon-forum-reply-edit-form-' + uniqueId" *ngIf="(post.id && !replyData.isEditing && replyData.replyingTo == post.id) || (!post.id && replyData.isEditing && replyData.replyingTo == post.parent)">
<ion-item>
<ion-label stacked>{{ 'addon.mod_forum.subject' | translate }}</ion-label>

View File

@ -2,4 +2,51 @@ ion-app.app-root addon-mod-forum-post {
.addon-forum-star {
color: $core-star-color;
}
.card-header .item {
.label {
margin-top: 4px;
h2 {
margin-top: 8px;
margin-bottom: 8px;
font-weight: bold;
ion-icon {
@include margin(0, 6px, 0, 0);
}
}
h3 {
font-size: 1.6rem;
}
}
ion-avatar {
width: $addon-forum-avatar-size;
height: $addon-forum-avatar-size;
min-width: $addon-forum-avatar-size;
min-height: $addon-forum-avatar-size;
&[item-start] {
@include margin(0, 8px, 0, 0);
}
img {
width: $addon-forum-avatar-size;
height: $addon-forum-avatar-size;
}
}
.addon-mod-forum-post-title,
.addon-mod-forum-post-info {
display: flex;
align-items: center;
}
.addon-mod-forum-post-title h2,
.addon-mod-forum-post-info .addon-mod-forum-post-author {
flex-grow: 1;
}
}
.addon-mod-forum-post-more-info div {
font-size: 1.4rem;
}
}