PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.3
Tutor LMS – eLearning and online course solution v4.0.3
4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / templates / dashboard / discussions / qna-card.php
tutor / templates / dashboard / discussions Last commit date
comment-card.php 3 weeks ago comment-form.php 3 weeks ago comment-list.php 3 weeks ago comment-replies.php 3 weeks ago comment-single.php 3 weeks ago qna-card.php 3 weeks ago qna-form.php 3 weeks ago qna-list.php 3 weeks ago qna-replies.php 3 weeks ago qna-single.php 3 weeks ago
qna-card.php
359 lines
1 <?php
2 /**
3 * Single Q&A card for Q&A list.
4 *
5 * @package Tutor\Templates
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 4.0.0
9 */
10
11 defined( 'ABSPATH' ) || exit;
12
13 use Tutor\Components\Constants\Size;
14 use TUTOR\Icon;
15 use Tutor\Components\SvgIcon;
16 use Tutor\Components\Constants\Color;
17 use Tutor\Components\Avatar;
18 use Tutor\Components\Button;
19 use Tutor\Components\Constants\Variant;
20 use Tutor\Components\PreviewTrigger;
21 use Tutor\Helpers\UrlHelper;
22 use TUTOR\User;
23
24 $current_user_id = get_current_user_id();
25 $is_user_asker = $current_user_id === (int) $question->user_id;
26 $context = 'frontend-dashboard-qna-table-' . $view_as;
27 $key_slug = 'frontend-dashboard-qna-table-student' === $context ? '_' . $current_user_id : '';
28 $meta = $question->meta;
29 $is_read = (int) tutor_utils()->array_get( 'tutor_qna_read' . $key_slug, $meta, 0 );
30 $is_unread = 0 === $is_read;
31 $text_mark_as = $is_unread ? __( 'Mark as Read', 'tutor' ) : __( 'Mark as Unread', 'tutor' );
32 $is_solved = (int) tutor_utils()->array_get( 'tutor_qna_solved', $meta, 0 );
33 $is_important = (int) tutor_utils()->array_get( 'tutor_qna_important', $meta, 0 );
34
35 $limit = 60;
36 $content = wp_strip_all_tags( $question->comment_content );
37 $content = strlen( $content ) > $limit ? substr( $content, 0, $limit ) . '...' : $content;
38
39 $question_id = $question->comment_ID;
40 $last_reply = null;
41 $answers = tutor_utils()->get_qa_answer_by_question( $question_id, 'DESC', 'frontend' );
42
43 if ( ! empty( $answers ) ) {
44 $last_reply = $answers[0];
45 }
46
47 $single_url = UrlHelper::add_query_params(
48 $discussion_url,
49 array(
50 'tab' => 'qna',
51 'id' => $question_id,
52 )
53 );
54 ?>
55 <div
56 class="tutor-discussion-card tutor-flex-column"
57 data-question-id="<?php echo esc_attr( (int) $question_id ); ?>"
58 x-show="editingId !== <?php echo (int) $question_id; ?>"
59 x-data="{
60 ...tutorPopover({ placement: 'bottom-end' }),
61 isUnread: <?php echo $is_unread ? 'true' : 'false'; ?>,
62 isArchived: <?php echo tutor_utils()->array_get( 'tutor_qna_archived', $meta, 0 ) ? 'true' : 'false'; ?>,
63 isSolved: <?php echo $is_solved ? 'true' : 'false'; ?>,
64 isImportant: <?php echo $is_important ? 'true' : 'false'; ?>
65 }"
66 :class="{ 'unread': isUnread, 'active': open }"
67 @tutor-qna-action-success.window="
68 if ($event.detail.questionId === <?php echo esc_html( $question_id ); ?>) {
69 if ($event.detail.action === 'read') isUnread = !isUnread;
70 if ($event.detail.action === 'archived') isArchived = !isArchived;
71 if ($event.detail.action === 'solved') isSolved = !isSolved;
72 if ($event.detail.action === 'important') isImportant = !isImportant;
73 }
74 "
75 >
76 <div class="tutor-flex tutor-gap-4 tutor-w-full">
77 <?php Avatar::make()->user( $question->user_id )->size( Size::SIZE_32 )->render(); ?>
78 <div class="tutor-discussion-card-content">
79 <div class="tutor-discussion-card-top">
80 <div class="tutor-discussion-card-author tutor-flex-shrink-0"><?php echo esc_html( $question->comment_author ); ?></div>
81 <div class="tutor-flex tutor-items-center tutor-gap-2 tutor-overflow-hidden">
82 <span class="tutor-text-subdued tutor-text-subdued tutor-flex-shrink-0"><?php echo esc_html__( 'asked in', 'tutor' ); ?></span>
83 <div class="tutor-min-w-0 tutor-flex-1">
84 <?php PreviewTrigger::make()->id( $question->course_id )->render(); ?>
85 </div>
86 </div>
87 </div>
88 <a href="<?php echo esc_url( $single_url ); ?>" class="tutor-discussion-card-title tutor-break-words" id="<?php echo esc_attr( 'tutor-qna-text-' . (int) $question_id ); ?>"><?php echo wp_kses_post( $content ); ?></a>
89 <div class="tutor-flex tutor-items-center tutor-justify-between tutor-sm-mt-4">
90 <div class="tutor-discussion-card-meta">
91 <button
92 @click="toggleReply(<?php echo (int) $question_id; ?>)"
93 class="tutor-discussion-card-meta-reply-button"
94 type="button"
95 >
96 <?php esc_html_e( 'Reply', 'tutor' ); ?>
97 </button>
98 <a href="<?php echo esc_url( $single_url ); ?>" class="tutor-flex tutor-items-center tutor-gap-2">
99 <?php SvgIcon::make()->name( Icon::COMMENTS )->size( 20 )->render(); ?>
100 <span class="tutor-discussion-card-reply-count tutor-text-subdued"><?php echo esc_html( $question->answer_count ); ?></span>
101 </a>
102
103 <?php if ( $last_reply ) { ?>
104 <div class="tutor-flex tutor-items-center tutor-gap-3 tutor-sm-ml-2">
105 <?php Avatar::make()->user( $last_reply->user_id )->size( Size::SIZE_20 )->render(); ?>
106 <div class="tutor-text-small">
107 <?php
108 // translators: %s human-readable time difference.
109 echo esc_html( sprintf( _x( '%s ago', 'human-readable time difference', 'tutor' ), human_time_diff( strtotime( $question->comment_date_gmt ) ) ) );
110 ?>
111 </div>
112 </div>
113 <?php } else { ?>
114 <div class="tutor-text-small">
115 <?php
116 /* translators: %s human-readable time difference. */
117 echo esc_html( sprintf( __( '%s ago', 'tutor' ), human_time_diff( strtotime( $question->comment_date_gmt ) ) ) );
118 ?>
119 </div>
120 <?php } ?>
121 </div>
122 <?php if ( User::is_instructor_view() ) : ?>
123 <div class="tutor-flex tutor-gap-2 tutor-sm-hidden">
124 <div x-data="tutorTooltip({ placement: 'top', arrow: 'center' })" class="tutor-tooltip-wrap">
125 <button
126 x-ref="trigger"
127 class="tutor-btn tutor-btn-ghost tutor-btn-x-small tutor-btn-icon tutor-text-subdued"
128 @click="handleQnASingleAction(<?php echo esc_html( $question_id ); ?>, 'solved')"
129 :disabled="qnaSingleActionMutation?.isPending && currentAction === 'solved' && currentQuestionId === <?php echo esc_html( $question_id ); ?>"
130 :aria-label="isSolved ? '<?php echo esc_js( __( 'Mark as Unresolved', 'tutor' ) ); ?>' : '<?php echo esc_js( __( 'Mark as Solved', 'tutor' ) ); ?>'"
131 >
132 <template x-if="qnaSingleActionMutation?.isPending && currentAction === 'solved' && currentQuestionId === <?php echo esc_html( $question_id ); ?>">
133 <?php SvgIcon::make()->name( Icon::SPINNER )->size( 14 )->attr( 'class', 'tutor-animate-spin' )->render(); ?>
134 </template>
135 <template x-if="!(qnaSingleActionMutation?.isPending && currentAction === 'solved' && currentQuestionId === <?php echo esc_html( $question_id ); ?>)">
136 <span class="tutor-flex">
137 <template x-if="isSolved">
138 <?php SvgIcon::make()->name( Icon::COMPLETED_FILL )->size( 16 )->color( Color::SUCCESS_PRIMARY )->render(); ?>
139 </template>
140 <template x-if="!isSolved">
141 <?php SvgIcon::make()->name( Icon::COMPLETED_CIRCLE )->render(); ?>
142 </template>
143 </span>
144 </template>
145 </button>
146 <div
147 x-ref="content"
148 x-show="open"
149 x-cloak
150 x-transition
151 class="tutor-tooltip"
152 x-text="isSolved
153 ? '<?php esc_html_e( 'Solved', 'tutor' ); ?>'
154 : '<?php esc_html_e( 'Unresolved', 'tutor' ); ?>'"
155 >
156 </div>
157 </div>
158 <div x-data="tutorTooltip({ placement: 'top', arrow: 'center' })" class="tutor-tooltip-wrap">
159 <button
160 x-ref="trigger"
161 class="tutor-btn tutor-btn-ghost tutor-btn-x-small tutor-btn-icon tutor-text-subdued"
162 @click="handleQnASingleAction(<?php echo esc_html( $question_id ); ?>, 'important')"
163 :disabled="qnaSingleActionMutation?.isPending && currentAction === 'important' && currentQuestionId === <?php echo esc_html( $question_id ); ?>"
164 :aria-label="isImportant ? '<?php echo esc_js( __( 'Mark as Not Important', 'tutor' ) ); ?>' : '<?php echo esc_js( __( 'Mark as Important', 'tutor' ) ); ?>'"
165 >
166 <template x-if="qnaSingleActionMutation?.isPending && currentAction === 'important' && currentQuestionId === <?php echo esc_html( $question_id ); ?>">
167 <?php SvgIcon::make()->name( Icon::SPINNER )->size( 14 )->attr( 'class', 'tutor-animate-spin' )->render(); ?>
168 </template>
169 <template x-if="!(qnaSingleActionMutation?.isPending && currentAction === 'important' && currentQuestionId === <?php echo esc_html( $question_id ); ?>)">
170 <span class="tutor-flex">
171 <template x-if="isImportant">
172 <?php SvgIcon::make()->name( Icon::BOOKMARK_FILL )->size( 16 )->color( Color::EXCEPTION4 )->render(); ?>
173 </template>
174 <template x-if="!isImportant">
175 <?php SvgIcon::make()->name( Icon::BOOKMARK )->render(); ?>
176 </template>
177 </span>
178 </template>
179 </button>
180 <div
181 x-ref="content"
182 x-show="open"
183 x-cloak
184 x-transition
185 class="tutor-tooltip"
186 x-text="isImportant
187 ? '<?php esc_html_e( 'This conversation is important', 'tutor' ); ?>'
188 : '<?php esc_html_e( 'Mark this conversation as important', 'tutor' ); ?>'"
189 >
190 </div>
191 </div>
192 </div>
193 <?php endif; ?>
194 </div>
195 </div>
196 <div class="tutor-discussion-card-actions" x-show="replyingId !== <?php echo (int) $question_id; ?>" x-cloak>
197 <?php
198 Button::make()
199 ->variant( Variant::PRIMARY )
200 ->size( Size::X_SMALL )
201 ->label( __( 'Reply', 'tutor' ) )
202 ->size( Size::X_SMALL )
203 ->attr( '@click', 'toggleReply(' . (int) $question_id . ')' )
204 ->attr( 'class', 'tutor-force-sm-hidden' )
205 ->attr( 'type', 'button' )
206 ->render();
207 ?>
208 <div class="tutor-flex">
209 <?php
210 Button::make()
211 ->label( __( 'More options', 'tutor' ) )
212 ->variant( Variant::SECONDARY )
213 ->size( Size::X_SMALL )
214 ->icon( Icon::ELLIPSES, 'left', Size::SIZE_16, Color::SECONDARY )
215 ->icon_only()
216 ->attr( 'x-ref', 'trigger' )
217 ->attr( '@click', 'toggle()' )
218 ->attr( 'class', 'tutor-discussion-card-actions-trigger' )
219 ->render();
220 ?>
221
222 <div x-ref="content" x-show="open" x-transition.origin.right.top x-cloak @click.outside="handleClickOutside()" class="tutor-popover">
223 <div class="tutor-popover-menu">
224 <?php if ( User::is_instructor_view() ) : ?>
225 <button
226 class="tutor-popover-menu-item tutor-gap-5 tutor-force-hidden tutor-force-sm-flex"
227 @click="handleQnASingleAction(<?php echo esc_html( $question_id ); ?>, 'solved')"
228 :disabled="qnaSingleActionMutation?.isPending"
229 >
230 <template x-if="qnaSingleActionMutation?.isPending && currentAction === 'solved' && currentQuestionId === <?php echo esc_html( $question_id ); ?>">
231 <?php SvgIcon::make()->name( Icon::SPINNER )->size( 20 )->color( Color::SECONDARY )->attr( 'class', 'tutor-animate-spin' )->render(); ?>
232 </template>
233 <template x-if="!(qnaSingleActionMutation?.isPending && currentAction === 'solved' && currentQuestionId === <?php echo esc_html( $question_id ); ?>)">
234 <span class="tutor-flex">
235 <template x-if="isSolved">
236 <?php SvgIcon::make()->name( Icon::COMPLETED_FILL )->size( 20 )->color( Color::SUCCESS_PRIMARY )->render(); ?>
237 </template>
238 <template x-if="!isSolved">
239 <?php SvgIcon::make()->name( Icon::COMPLETED_CIRCLE )->size( 20 )->render(); ?>
240 </template>
241 </span>
242 </template>
243 <?php esc_html_e( 'Solved', 'tutor' ); ?>
244 </button>
245
246 <button
247 class="tutor-popover-menu-item tutor-gap-5 tutor-force-hidden tutor-force-sm-flex"
248 @click="handleQnASingleAction(<?php echo esc_html( $question_id ); ?>, 'important')"
249 :disabled="qnaSingleActionMutation?.isPending"
250 >
251 <template x-if="qnaSingleActionMutation?.isPending && currentAction === 'important' && currentQuestionId === <?php echo esc_html( $question_id ); ?>">
252 <?php SvgIcon::make()->name( Icon::SPINNER )->size( 20 )->color( Color::SECONDARY )->attr( 'class', 'tutor-animate-spin' )->render(); ?>
253 </template>
254 <template x-if="!(qnaSingleActionMutation?.isPending && currentAction === 'important' && currentQuestionId === <?php echo esc_html( $question_id ); ?>)">
255 <span class="tutor-flex">
256 <template x-if="isImportant">
257 <?php SvgIcon::make()->name( Icon::BOOKMARK_FILL )->size( 20 )->color( Color::EXCEPTION4 )->render(); ?>
258 </template>
259 <template x-if="!isImportant">
260 <?php SvgIcon::make()->name( Icon::BOOKMARK )->size( 20 )->render(); ?>
261 </template>
262 </span>
263 </template>
264 <?php esc_html_e( 'Important', 'tutor' ); ?>
265 </button>
266
267 <button
268 class="tutor-popover-menu-item tutor-gap-5"
269 @click="handleQnASingleAction(<?php echo esc_html( $question_id ); ?>, 'archived')"
270 :disabled="qnaSingleActionMutation?.isPending"
271 >
272 <template x-if="qnaSingleActionMutation?.isPending && currentAction === 'archived' && currentQuestionId === <?php echo esc_html( $question_id ); ?>">
273 <?php SvgIcon::make()->name( Icon::SPINNER )->size( 20 )->color( Color::SECONDARY )->attr( 'class', 'tutor-animate-spin' )->render(); ?>
274 </template>
275 <template x-if="!(qnaSingleActionMutation?.isPending && currentAction === 'archived' && currentQuestionId === <?php echo esc_html( $question_id ); ?>)">
276 <?php SvgIcon::make()->name( Icon::ARCHIVE_2 )->size( 20 )->render(); ?>
277 </template>
278 <span x-text="isArchived ? '<?php echo esc_js( __( 'Un-Archive', 'tutor' ) ); ?>' : '<?php echo esc_js( __( 'Archive', 'tutor' ) ); ?>'"></span>
279 </button>
280 <?php endif; ?>
281
282 <button
283 class="tutor-popover-menu-item tutor-gap-5"
284 @click="handleQnASingleAction(<?php echo esc_html( $question_id ); ?>, 'read', { context: '<?php echo esc_html( $context ); ?>' })"
285 :disabled="qnaSingleActionMutation?.isPending"
286 >
287 <template x-if="qnaSingleActionMutation?.isPending && currentAction === 'read' && currentQuestionId === <?php echo esc_html( $question_id ); ?>">
288 <?php SvgIcon::make()->name( Icon::SPINNER )->size( 20 )->color( Color::SECONDARY )->attr( 'class', 'tutor-animate-spin' )->render(); ?>
289 </template>
290 <template x-if="!(qnaSingleActionMutation?.isPending && currentAction === 'read' && currentQuestionId === <?php echo esc_html( $question_id ); ?>)">
291 <span class="tutor-flex">
292 <template x-if="isUnread">
293 <?php SVGIcon::make()->name( Icon::READ )->size( 20 )->render(); ?>
294 </template>
295 <template x-if="!isUnread">
296 <?php SVGIcon::make()->name( Icon::UNREAD )->size( 20 )->render(); ?>
297 </template>
298 </span>
299 </template>
300 <span x-text="isUnread ? '<?php echo esc_js( __( 'Mark as Read', 'tutor' ) ); ?>' : '<?php echo esc_js( __( 'Mark as Unread', 'tutor' ) ); ?>'"></span>
301 </button>
302
303 <?php if ( $is_user_asker ) : ?>
304 <button class="tutor-popover-menu-item tutor-gap-5" @click="setEditing(<?php echo (int) $question_id; ?>, 'qna'); hide()">
305 <?php SvgIcon::make()->name( Icon::EDIT_2 )->size( 20 )->render(); ?>
306 <?php esc_html_e( 'Edit', 'tutor' ); ?>
307 </button>
308 <?php endif; ?>
309
310 <button
311 class="tutor-popover-menu-item tutor-gap-5 tutor-sm-border-t"
312 @click="hide(); TutorCore.modal.showModal('tutor-qna-delete-modal', { question_id: <?php echo esc_html( $question_id ); ?> });"
313 >
314 <?php SvgIcon::make()->name( Icon::DELETE_2 )->size( 20 )->render(); ?>
315 <?php esc_html_e( 'Delete', 'tutor' ); ?>
316 </button>
317 </div>
318 </div>
319 </div>
320 </div>
321 </div>
322
323 <div x-show="replyingId === <?php echo (int) $question_id; ?>" x-cloak class="tutor-card tutor-surface-l1-hover tutor-mt-4 tutor-w-full">
324 <?php
325 tutor_load_template(
326 'dashboard.discussions.qna-form',
327 array(
328 'form_id' => 'qna-reply-form-' . (int) $question_id,
329 'submit_handler' => '(data) => replyQnAMutation?.mutate({ ...data, question_id: ' . (int) $question_id . ', course_id: ' . (int) $question->course_id . ', reply_context: "list" })',
330 'cancel_handler' => 'setReplying(null)',
331 'is_pending' => 'replyQnAMutation?.isPending',
332 'placeholder' => __( 'Just drop your response here!', 'tutor' ),
333 'label' => __( 'Reply', 'tutor' ),
334 'submit_label' => __( 'Save', 'tutor' ),
335 'keep_footer_visible' => true,
336 )
337 );
338 ?>
339 </div>
340
341 <?php if ( $is_user_asker ) : ?>
342 <div x-show="editingId === <?php echo (int) $question_id; ?>" x-cloak class="tutor-card tutor-surface-l1-hover tutor-w-full">
343 <?php
344 tutor_load_template(
345 'dashboard.discussions.qna-form',
346 array(
347 'form_id' => 'qna-edit-' . (int) $question_id,
348 'default_value' => $question->comment_content,
349 'submit_handler' => '(data) => updateQnAMutation?.mutate({ ...data, question_id: ' . (int) $question->comment_ID . ' })',
350 'cancel_handler' => 'setEditing(null)',
351 'is_pending' => 'updateQnAMutation?.isPending',
352 'keep_footer_visible' => true,
353 )
354 );
355 ?>
356 </div>
357 <?php endif; ?>
358 </div>
359